Index: boot/Makefile
===================================================================
--- boot/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ boot/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -65,10 +65,14 @@
 	done
 	for drv in $(RD_DRVS) ; do \
-		mkdir -p "$(DIST_PATH)/$(DRVS_PATH)/$$drv" ; \
-		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$drv/$$drv" "$(DIST_PATH)/$(DRVS_PATH)/$$drv/$$drv" ; \
-		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$drv/$$drv.ma" "$(DIST_PATH)/$(DRVS_PATH)/$$drv/$$drv.ma" ; \
+		drv_dir="`dirname "$$drv"`" ; \
+		drv_name="`basename "$$drv"`" ; \
+		mkdir -p "$(DIST_PATH)/$(DRVS_PATH)/$$drv_name" ; \
+		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$drv_dir/$$drv_name/$$drv_name" "$(DIST_PATH)/$(DRVS_PATH)/$$drv_name/" ; \
+		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$drv_dir/$$drv_name/$$drv_name.ma" "$(DIST_PATH)/$(DRVS_PATH)/$$drv_name/" ; \
 	done
 	for file in $(RD_DRV_CFG) ; do \
-		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$file" "$(DIST_PATH)/$(DRVS_PATH)/$$file" ; \
+		file_dir="`dirname "$$file"`" ; \
+		file_name="`basename "$$file"`" ; \
+		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$file_dir/$$file_name/$$file_name.dev" "$(DIST_PATH)/$(DRVS_PATH)/$$file_name/" ; \
 	done
 	
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ boot/Makefile.common	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -110,13 +110,13 @@
 	$(USPACE_PATH)/srv/net/net/net \
 	$(USPACE_PATH)/srv/devman/devman
-	
+
 RD_DRVS = \
-	root \
-	rootvirt \
-	test1 \
-	test2 \
-	test3
-
-RD_DRV_CFG = 
+	infrastructure/root \
+	infrastructure/rootvirt \
+	test/test1 \
+	test/test2 \
+	test/test3
+
+RD_DRV_CFG =
 
 RD_LIBS =
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ boot/arch/amd64/Makefile.inc	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -35,26 +35,25 @@
 
 RD_SRVS_NON_ESSENTIAL += \
-	$(USPACE_PATH)/srv/bd/ata_bd/ata_bd \
-	$(USPACE_PATH)/srv/hid/char_mouse/char_ms
+	$(USPACE_PATH)/srv/bd/ata_bd/ata_bd
 
 RD_DRVS += \
-	rootpc \
-	pciintel \
-	isa \
-	ns8250 \
-	ehci_hcd \
-	ohci \
-	uhci_hcd \
-	uhci_rhd \
-	usbflbk \
-	usbhub \
-	usbhid \
-	usbmast \
-	usbmid \
-	usbmouse \
-	vhc
+	infrastructure/rootpc \
+	bus/pci/pciintel \
+	bus/isa \
+	char/ns8250 \
+	bus/usb/ehci\
+	bus/usb/ohci \
+	bus/usb/uhci \
+	bus/usb/uhcirh \
+	bus/usb/usbflbk \
+	bus/usb/usbhub \
+	bus/usb/usbhid \
+	bus/usb/usbmast \
+	bus/usb/usbmid \
+	bus/usb/usbmouse \
+	bus/usb/vhc
 
 RD_DRV_CFG += \
-	isa/isa.dev
+	bus/isa
 
 BOOT_OUTPUT = $(ROOT_PATH)/image.iso
Index: boot/arch/ppc32/Makefile.inc
===================================================================
--- boot/arch/ppc32/Makefile.inc	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ boot/arch/ppc32/Makefile.inc	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -43,6 +43,6 @@
 	$(USPACE_PATH)/srv/hw/bus/cuda_adb/cuda_adb
 
-RD_SRVS_NON_ESSENTIAL += \
-	$(USPACE_PATH)/srv/hid/adb_mouse/adb_ms
+RD_DRVS += \
+	infrastructure/rootmac
 
 SOURCES = \
Index: kernel/arch/sparc64/src/drivers/tick.c
===================================================================
--- kernel/arch/sparc64/src/drivers/tick.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/arch/sparc64/src/drivers/tick.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -44,6 +44,4 @@
 #include <debug.h>
 
-#define TICK_RESTART_TIME	50	/* Worst case estimate. */
-
 /** Initialize tick and stick interrupt. */
 void tick_init(void)
@@ -51,4 +49,5 @@
 	/* initialize TICK interrupt */
 	tick_compare_reg_t compare;
+	softint_reg_t clear;
 
 	interrupt_register(14, "tick_int", tick_interrupt);
@@ -59,8 +58,11 @@
 	tick_compare_write(compare.value);
 
+	clear.value = 0;
+	clear.tick_int = 1;
+	clear_softint_write(clear.value);
+
 #if defined (US3) || defined (SUN4V)
 	/* disable STICK interrupts and clear any pending ones */
 	tick_compare_reg_t stick_compare;
-	softint_reg_t clear;
 
 	stick_compare.value = stick_compare_read();
Index: kernel/genarch/src/mm/asid.c
===================================================================
--- kernel/genarch/src/mm/asid.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/genarch/src/mm/asid.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -97,6 +97,6 @@
 		 * inactive address space.
 		 */
-		ASSERT(!list_empty(&inactive_as_with_asid_head));
-		tmp = inactive_as_with_asid_head.next;
+		tmp = list_first(&inactive_as_with_asid_list);
+		ASSERT(tmp != NULL);
 		list_remove(tmp);
 		
Index: kernel/generic/include/adt/btree.h
===================================================================
--- kernel/generic/include/adt/btree.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/adt/btree.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -89,5 +89,5 @@
 typedef struct {
 	btree_node_t *root;	/**< B-tree root node pointer. */
-	link_t leaf_head;	/**< Leaf-level list head. */
+	list_t leaf_list;	/**< List of leaves. */
 } btree_t;
 
Index: kernel/generic/include/adt/hash_table.h
===================================================================
--- kernel/generic/include/adt/hash_table.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/adt/hash_table.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -68,5 +68,5 @@
 /** Hash table structure. */
 typedef struct {
-	link_t *entry;
+	list_t *entry;
 	size_t entries;
 	size_t max_keys;
Index: kernel/generic/include/adt/list.h
===================================================================
--- kernel/generic/include/adt/list.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/adt/list.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -39,5 +40,5 @@
 #include <trace.h>
 
-/** Doubly linked list head and link type. */
+/** Doubly linked list link. */
 typedef struct link {
 	struct link *prev;  /**< Pointer to the previous item in the list. */
@@ -45,4 +46,9 @@
 } link_t;
 
+/** Doubly linked list. */
+typedef struct list {
+	link_t head;  /**< List head. Does not have any data. */
+} list_t;
+
 /** Declare and initialize statically allocated list.
  *
@@ -51,7 +57,9 @@
  */
 #define LIST_INITIALIZE(name) \
-	link_t name = { \
-		.prev = &name, \
-		.next = &name \
+	list_t name = { \
+		.head = { \
+			.prev = &(name).head, \
+			.next = &(name).head \
+		} \
 	}
 
@@ -60,6 +68,9 @@
 
 #define list_foreach(list, iterator) \
-	for (link_t *iterator = (list).next; \
-	    iterator != &(list); iterator = iterator->next)
+	for (link_t *iterator = (list).head.next; \
+	    iterator != &(list).head; iterator = iterator->next)
+
+#define assert_link_not_used(link) \
+	ASSERT((link)->prev == NULL && (link)->next == NULL)
 
 /** Initialize doubly-linked circular list link
@@ -80,11 +91,33 @@
  * Initialize doubly-linked circular list.
  *
- * @param list Pointer to link_t structure representing the list.
- *
- */
-NO_TRACE static inline void list_initialize(link_t *list)
-{
-	list->prev = list;
-	list->next = list;
+ * @param list Pointer to list_t structure.
+ *
+ */
+NO_TRACE static inline void list_initialize(list_t *list)
+{
+	list->head.prev = &list->head;
+	list->head.next = &list->head;
+}
+
+/** Insert item before another item in doubly-linked circular list.
+ *
+ */
+static inline void list_insert_before(link_t *lnew, link_t *lold)
+{
+	lnew->next = lold;
+	lnew->prev = lold->prev;
+	lold->prev->next = lnew;
+	lold->prev = lnew;
+}
+
+/** Insert item after another item in doubly-linked circular list.
+ *
+ */
+static inline void list_insert_after(link_t *lnew, link_t *lold)
+{
+	lnew->prev = lold;
+	lnew->next = lold->next;
+	lold->next->prev = lnew;
+	lold->next = lnew;
 }
 
@@ -94,13 +127,10 @@
  *
  * @param link Pointer to link_t structure to be added.
- * @param list Pointer to link_t structure representing the list.
- *
- */
-NO_TRACE static inline void list_prepend(link_t *link, link_t *list)
-{
-	link->next = list->next;
-	link->prev = list;
-	list->next->prev = link;
-	list->next = link;
+ * @param list Pointer to list_t structure.
+ *
+ */
+NO_TRACE static inline void list_prepend(link_t *link, list_t *list)
+{
+	list_insert_after(link, &list->head);
 }
 
@@ -110,29 +140,10 @@
  *
  * @param link Pointer to link_t structure to be added.
- * @param list Pointer to link_t structure representing the list.
- *
- */
-NO_TRACE static inline void list_append(link_t *link, link_t *list)
-{
-	link->prev = list->prev;
-	link->next = list;
-	list->prev->next = link;
-	list->prev = link;
-}
-
-/** Insert item before another item in doubly-linked circular list.
- *
- */
-static inline void list_insert_before(link_t *link, link_t *list)
-{
-	list_append(link, list);
-}
-
-/** Insert item after another item in doubly-linked circular list.
- *
- */
-static inline void list_insert_after(link_t *link, link_t *list)
-{
-	list_prepend(list, link);
+ * @param list Pointer to list_t structure.
+ *
+ */
+NO_TRACE static inline void list_append(link_t *link, list_t *list)
+{
+	list_insert_before(link, &list->head);
 }
 
@@ -156,15 +167,15 @@
  * Query emptiness of doubly-linked circular list.
  *
- * @param list Pointer to link_t structure representing the list.
- *
- */
-NO_TRACE static inline int list_empty(link_t *list)
-{
-	return (list->next == list);
-}
-
-/** Get head item of a list.
- *
- * @param list Pointer to link_t structure representing the list.
+ * @param list Pointer to lins_t structure.
+ *
+ */
+NO_TRACE static inline int list_empty(list_t *list)
+{
+	return (list->head.next == &list->head);
+}
+
+/** Get first item in list.
+ *
+ * @param list Pointer to list_t structure.
  *
  * @return Head item of the list.
@@ -172,7 +183,20 @@
  *
  */
-static inline link_t *list_head(link_t *list)
-{
-	return ((list->next == list) ? NULL : list->next);
+static inline link_t *list_first(list_t *list)
+{
+	return ((list->head.next == &list->head) ? NULL : list->head.next);
+}
+
+/** Get last item in list.
+ *
+ * @param list Pointer to list_t structure.
+ *
+ * @return Head item of the list.
+ * @return NULL if the list is empty.
+ *
+ */
+static inline link_t *list_last(list_t *list)
+{
+	return ((list->head.prev == &list->head) ? NULL : list->head.prev);
 }
 
@@ -231,5 +255,5 @@
 }
 
-/** Get n-th item of a list.
+/** Get n-th item in a list.
  *
  * @param list Pointer to link_t structure representing the list.
@@ -240,5 +264,5 @@
  *
  */
-static inline link_t *list_nth(link_t *list, unsigned int n)
+static inline link_t *list_nth(list_t *list, unsigned int n)
 {
 	unsigned int cnt = 0;
@@ -254,7 +278,7 @@
 }
 
-extern int list_member(const link_t *, const link_t *);
-extern void list_concat(link_t *, link_t *);
-extern unsigned int list_count(const link_t *);
+extern int list_member(const link_t *, const list_t *);
+extern void list_concat(list_t *, list_t *);
+extern unsigned int list_count(const list_t *);
 
 #endif
Index: kernel/generic/include/console/chardev.h
===================================================================
--- kernel/generic/include/console/chardev.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/console/chardev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -88,5 +88,5 @@
 	/** Fields suitable for multiplexing. */
 	link_t link;
-	link_t list;
+	list_t list;
 	
 	/** Implementation of outdev operations. */
Index: kernel/generic/include/console/kconsole.h
===================================================================
--- kernel/generic/include/console/kconsole.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/console/kconsole.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -91,5 +91,5 @@
 
 SPINLOCK_EXTERN(cmd_lock);
-extern link_t cmd_head;
+extern list_t cmd_list;
 
 extern void kconsole_init(void);
Index: kernel/generic/include/cpu.h
===================================================================
--- kernel/generic/include/cpu.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/cpu.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -59,5 +59,5 @@
 	
 	IRQ_SPINLOCK_DECLARE(timeoutlock);
-	link_t timeout_active_head;
+	list_t timeout_active_list;
 	
 	/**
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/ipc/ipc.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -166,18 +166,18 @@
 	
 	/** Phones connected to this answerbox. */
-	link_t connected_phones;
+	list_t connected_phones;
 	/** Received calls. */
-	link_t calls;
-	link_t dispatched_calls;  /* Should be hash table in the future */
+	list_t calls;
+	list_t dispatched_calls;  /* Should be hash table in the future */
 	
 	/** Answered calls. */
-	link_t answers;
+	list_t answers;
 	
 	IRQ_SPINLOCK_DECLARE(irq_lock);
 	
 	/** Notifications from IRQ handlers. */
-	link_t irq_notifs;
+	list_t irq_notifs;
 	/** IRQs with notifications to this answerbox. */
-	link_t irq_head;
+	list_t irq_list;
 } answerbox_t;
 
@@ -243,5 +243,5 @@
 extern void ipc_backsend_err(phone_t *, call_t *, sysarg_t);
 extern void ipc_answerbox_slam_phones(answerbox_t *, bool);
-extern void ipc_cleanup_call_list(link_t *);
+extern void ipc_cleanup_call_list(list_t *);
 
 extern void ipc_print_task(task_id_t);
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/mm/as.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -254,5 +254,5 @@
 
 extern as_operations_t *as_operations;
-extern link_t inactive_as_with_asid_head;
+extern list_t inactive_as_with_asid_list;
 
 extern void as_init(void);
Index: kernel/generic/include/mm/buddy.h
===================================================================
--- kernel/generic/include/mm/buddy.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/mm/buddy.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -72,5 +72,5 @@
 	/** Maximal order of block which can be stored by buddy system. */
 	uint8_t max_order;
-	link_t *order;
+	list_t *order;
 	buddy_system_operations_t *op;
 	/** Pointer to be used by the implementation. */
Index: kernel/generic/include/mm/slab.h
===================================================================
--- kernel/generic/include/mm/slab.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/mm/slab.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -111,9 +111,9 @@
 	
 	/* Slabs */
-	link_t full_slabs;     /**< List of full slabs */
-	link_t partial_slabs;  /**< List of partial slabs */
+	list_t full_slabs;     /**< List of full slabs */
+	list_t partial_slabs;  /**< List of partial slabs */
 	SPINLOCK_DECLARE(slablock);
 	/* Magazines */
-	link_t magazines;  /**< List o full magazines */
+	list_t magazines;  /**< List o full magazines */
 	SPINLOCK_DECLARE(maglock);
 	
Index: kernel/generic/include/proc/scheduler.h
===================================================================
--- kernel/generic/include/proc/scheduler.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/proc/scheduler.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -48,6 +48,6 @@
 typedef struct {
 	IRQ_SPINLOCK_DECLARE(lock);
-	link_t rq_head;              /**< List of ready threads. */
-	size_t n;                    /**< Number of threads in rq_ready. */
+	list_t rq;			/**< List of ready threads. */
+	size_t n;			/**< Number of threads in rq_ready. */
 } runq_t;
 
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/proc/task.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -73,5 +73,5 @@
 	char name[TASK_NAME_BUFLEN];
 	/** List of threads contained in this task. */
-	link_t th_head;
+	list_t threads;
 	/** Address space. */
 	as_t *as;
@@ -94,5 +94,5 @@
 	stats_ipc_t ipc_info;   /**< IPC statistics */
 	/** List of synchronous answerboxes. */
-	link_t sync_box_head;
+	list_t sync_boxes;
 	
 #ifdef CONFIG_UDEBUG
Index: kernel/generic/include/synch/waitq.h
===================================================================
--- kernel/generic/include/synch/waitq.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/include/synch/waitq.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -63,5 +63,5 @@
 	
 	/** List of sleeping threads for which there was no missed_wakeup. */
-	link_t head;
+	list_t sleepers;
 } waitq_t;
 
Index: kernel/generic/src/adt/btree.c
===================================================================
--- kernel/generic/src/adt/btree.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/adt/btree.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -108,8 +108,8 @@
 void btree_create(btree_t *t)
 {
-	list_initialize(&t->leaf_head);
+	list_initialize(&t->leaf_list);
 	t->root = (btree_node_t *) slab_alloc(btree_node_slab, 0);
 	node_initialize(t->root);
-	list_append(&t->root->leaf_link, &t->leaf_head);
+	list_append(&t->root->leaf_link, &t->leaf_list);
 }
 
@@ -588,5 +588,5 @@
 		
 		if (LEAF_NODE(node)) {
-			list_prepend(&rnode->leaf_link, &node->leaf_link);
+			list_insert_after(&rnode->leaf_link, &node->leaf_link);
 		}
 		
@@ -953,5 +953,5 @@
 	ASSERT(LEAF_NODE(node));
 	
-	if (node->leaf_link.prev != &t->leaf_head)
+	if (node->leaf_link.prev != &t->leaf_list.head)
 		return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
 	else
@@ -972,5 +972,5 @@
 	ASSERT(LEAF_NODE(node));
 	
-	if (node->leaf_link.next != &t->leaf_head)
+	if (node->leaf_link.next != &t->leaf_list.head)
 		return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
 	else
@@ -987,9 +987,9 @@
 	size_t i;
 	int depth = t->root->depth;
-	link_t head, *cur;
+	list_t list;
 	
 	printf("Printing B-tree:\n");
-	list_initialize(&head);
-	list_append(&t->root->bfs_link, &head);
+	list_initialize(&list);
+	list_append(&t->root->bfs_link, &list);
 	
 	/*
@@ -997,10 +997,10 @@
 	 * Levels are distinguished from one another by node->depth.
 	 */
-	while (!list_empty(&head)) {
+	while (!list_empty(&list)) {
 		link_t *hlp;
 		btree_node_t *node;
 		
-		hlp = head.next;
-		ASSERT(hlp != &head);
+		hlp = list_first(&list);
+		ASSERT(hlp != NULL);
 		node = list_get_instance(hlp, btree_node_t, bfs_link);
 		list_remove(hlp);
@@ -1018,10 +1018,10 @@
 			printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
 			if (node->depth && node->subtree[i]) {
-				list_append(&node->subtree[i]->bfs_link, &head);
+				list_append(&node->subtree[i]->bfs_link, &list);
 			}
 		}
 		
 		if (node->depth && node->subtree[i])
-			list_append(&node->subtree[i]->bfs_link, &head);
+			list_append(&node->subtree[i]->bfs_link, &list);
 		
 		printf(")");
@@ -1031,5 +1031,5 @@
 	
 	printf("Printing list of leaves:\n");
-	for (cur = t->leaf_head.next; cur != &t->leaf_head; cur = cur->next) {
+	list_foreach(t->leaf_list, cur) {
 		btree_node_t *node;
 		
Index: kernel/generic/src/adt/hash_table.c
===================================================================
--- kernel/generic/src/adt/hash_table.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/adt/hash_table.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -62,9 +62,9 @@
 	ASSERT(max_keys > 0);
 	
-	h->entry = (link_t *) malloc(m * sizeof(link_t), 0);
+	h->entry = (list_t *) malloc(m * sizeof(list_t), 0);
 	if (!h->entry)
 		panic("Cannot allocate memory for hash table.");
 	
-	memsetb(h->entry, m * sizeof(link_t), 0);
+	memsetb(h->entry, m * sizeof(list_t), 0);
 	
 	for (i = 0; i < m; i++)
@@ -107,5 +107,4 @@
 link_t *hash_table_find(hash_table_t *h, sysarg_t key[])
 {
-	link_t *cur;
 	size_t chain;
 	
@@ -118,5 +117,5 @@
 	ASSERT(chain < h->entries);
 	
-	for (cur = h->entry[chain].next; cur != &h->entry[chain]; cur = cur->next) {
+	list_foreach(h->entry[chain], cur) {
 		if (h->op->compare(key, h->max_keys, cur)) {
 			/*
@@ -141,5 +140,4 @@
 {
 	size_t chain;
-	link_t *cur;
 	
 	ASSERT(h);
@@ -149,6 +147,8 @@
 	ASSERT(keys <= h->max_keys);
 	
+	
 	if (keys == h->max_keys) {
-	
+		link_t *cur;
+		
 		/*
 		 * All keys are known, hash_table_find() can be used to find the entry.
@@ -169,5 +169,7 @@
 	 */
 	for (chain = 0; chain < h->entries; chain++) {
-		for (cur = h->entry[chain].next; cur != &h->entry[chain]; cur = cur->next) {
+		link_t *cur;
+		for (cur = h->entry[chain].head.next; cur != &h->entry[chain].head;
+		    cur = cur->next) {
 			if (h->op->compare(key, keys, cur)) {
 				link_t *hlp;
Index: kernel/generic/src/adt/list.c
===================================================================
--- kernel/generic/src/adt/list.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/adt/list.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -43,19 +43,19 @@
 /** Check for membership
  *
- * Check whether link is contained in the list head.
- * The membership is defined as pointer equivalence.
+ * Check whether link is contained in a list.
+ * Membership is defined as pointer equivalence.
  *
- * @param link Item to look for.
- * @param head List to look in.
+ * @param link	Item to look for.
+ * @param list	List to look in.
  *
  * @return true if link is contained in head, false otherwise.
  *
  */
-int list_member(const link_t *link, const link_t *head)
+int list_member(const link_t *link, const list_t *list)
 {
 	bool found = false;
-	link_t *hlp = head->next;
+	link_t *hlp = list->head.next;
 	
-	while (hlp != head) {
+	while (hlp != &list->head) {
 		if (hlp == link) {
 			found = true;
@@ -68,25 +68,42 @@
 }
 
-
 /** Concatenate two lists
  *
- * Concatenate lists head1 and head2, producing a single
- * list head1 containing items from both (in head1, head2
- * order) and empty list head2.
+ * Concatenate lists @a list1 and @a list2, producing a single
+ * list @a list1 containing items from both (in @a list1, @a list2
+ * order) and empty list @a list2.
  *
- * @param head1 First list and concatenated output
- * @param head2 Second list and empty output.
+ * @param list1		First list and concatenated output
+ * @param list2 	Second list and empty output.
  *
  */
-void list_concat(link_t *head1, link_t *head2)
+void list_concat(list_t *list1, list_t *list2)
 {
-	if (list_empty(head2))
+	if (list_empty(list2))
 		return;
 
-	head2->next->prev = head1->prev;
-	head2->prev->next = head1;	
-	head1->prev->next = head2->next;
-	head1->prev = head2->prev;
-	list_initialize(head2);
+	list2->head.next->prev = list1->head.prev;
+	list2->head.prev->next = &list1->head;
+	list1->head.prev->next = list2->head.next;
+	list1->head.prev = list2->head.prev;
+	list_initialize(list2);
+}
+
+/** Count list items
+ *
+ * Return the number of items in the list.
+ *
+ * @param list		List to count.
+ * @return		Number of items in the list.
+ */
+unsigned int list_count(const list_t *list)
+{
+	unsigned int count = 0;
+	
+	list_foreach(*list, link) {
+		count++;
+	}
+	
+	return count;
 }
 
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/console/cmd.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -573,7 +573,6 @@
 	spinlock_lock(&cmd_lock);
 	
-	link_t *cur;
 	size_t len = 0;
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp;
 		hlp = list_get_instance(cur, cmd_info_t, link);
@@ -591,5 +590,5 @@
 	}
 	
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp;
 		hlp = list_get_instance(cur, cmd_info_t, link);
@@ -646,9 +645,7 @@
 int cmd_desc(cmd_arg_t *argv)
 {
-	link_t *cur;
-	
 	spinlock_lock(&cmd_lock);
 	
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp;
 		
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/console/console.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -124,7 +124,5 @@
 static void stdout_write(outdev_t *dev, wchar_t ch, bool silent)
 {
-	link_t *cur;
-	
-	for (cur = dev->list.next; cur != &dev->list; cur = cur->next) {
+	list_foreach(dev->list, cur) {
 		outdev_t *sink = list_get_instance(cur, outdev_t, link);
 		if ((sink) && (sink->op->write))
@@ -135,7 +133,5 @@
 static void stdout_redraw(outdev_t *dev)
 {
-	link_t *cur;
-	
-	for (cur = dev->list.next; cur != &dev->list; cur = cur->next) {
+	list_foreach(dev->list, cur) {
 		outdev_t *sink = list_get_instance(cur, outdev_t, link);
 		if ((sink) && (sink->op->redraw))
Index: kernel/generic/src/console/kconsole.c
===================================================================
--- kernel/generic/src/console/kconsole.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/console/kconsole.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -84,5 +84,5 @@
 
 SPINLOCK_INITIALIZE(cmd_lock);  /**< Lock protecting command list. */
-LIST_INITIALIZE(cmd_head);      /**< Command list. */
+LIST_INITIALIZE(cmd_list);      /**< Command list. */
 
 static wchar_t history[KCONSOLE_HISTORY][MAX_CMDLINE] = {};
@@ -113,6 +113,4 @@
 bool cmd_register(cmd_info_t *cmd)
 {
-	link_t *cur;
-	
 	spinlock_lock(&cmd_lock);
 	
@@ -120,5 +118,5 @@
 	 * Make sure the command is not already listed.
 	 */
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link);
 		
@@ -153,5 +151,5 @@
 	 * Now the command can be added.
 	 */
-	list_append(&cmd->link, &cmd_head);
+	list_append(&cmd->link, &cmd_list);
 	
 	spinlock_unlock(&cmd_lock);
@@ -176,7 +174,7 @@
 	
 	if (*startpos == NULL)
-		*startpos = cmd_head.next;
-	
-	for (; *startpos != &cmd_head; *startpos = (*startpos)->next) {
+		*startpos = cmd_list.head.next;
+	
+	for (; *startpos != &cmd_list.head; *startpos = (*startpos)->next) {
 		cmd_info_t *hlp = list_get_instance(*startpos, cmd_info_t, link);
 		
@@ -559,7 +557,6 @@
 	
 	cmd_info_t *cmd = NULL;
-	link_t *cur;
-	
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link);
 		spinlock_lock(&hlp->lock);
Index: kernel/generic/src/cpu/cpu.c
===================================================================
--- kernel/generic/src/cpu/cpu.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/cpu/cpu.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -82,5 +82,5 @@
 			for (j = 0; j < RQ_COUNT; j++) {
 				irq_spinlock_initialize(&cpus[i].rq[j].lock, "cpus[].rq[].lock");
-				list_initialize(&cpus[i].rq[j].rq_head);
+				list_initialize(&cpus[i].rq[j].rq);
 			}
 		}
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/ipc/ipc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -128,5 +128,5 @@
 	list_initialize(&box->answers);
 	list_initialize(&box->irq_notifs);
-	list_initialize(&box->irq_head);
+	list_initialize(&box->irq_list);
 	box->task = task;
 }
@@ -183,5 +183,5 @@
 	 */
 	irq_spinlock_lock(&TASK->lock, true);
-	list_append(&sync_box->sync_box_link, &TASK->sync_box_head);
+	list_append(&sync_box->sync_box_link, &TASK->sync_boxes);
 	irq_spinlock_unlock(&TASK->lock, true);
 	
@@ -450,5 +450,6 @@
 		irq_spinlock_lock(&box->irq_lock, false);
 		
-		request = list_get_instance(box->irq_notifs.next, call_t, link);
+		request = list_get_instance(list_first(&box->irq_notifs),
+		    call_t, link);
 		list_remove(&request->link);
 		
@@ -459,5 +460,6 @@
 		
 		/* Handle asynchronous answers */
-		request = list_get_instance(box->answers.next, call_t, link);
+		request = list_get_instance(list_first(&box->answers),
+		    call_t, link);
 		list_remove(&request->link);
 		atomic_dec(&request->data.phone->active_calls);
@@ -467,5 +469,6 @@
 		
 		/* Handle requests */
-		request = list_get_instance(box->calls.next, call_t, link);
+		request = list_get_instance(list_first(&box->calls),
+		    call_t, link);
 		list_remove(&request->link);
 		
@@ -494,8 +497,8 @@
  *
  */
-void ipc_cleanup_call_list(link_t *lst)
+void ipc_cleanup_call_list(list_t *lst)
 {
 	while (!list_empty(lst)) {
-		call_t *call = list_get_instance(lst->next, call_t, link);
+		call_t *call = list_get_instance(list_first(lst), call_t, link);
 		if (call->buffer)
 			free(call->buffer);
@@ -526,5 +529,5 @@
 	irq_spinlock_lock(&box->lock, true);
 	while (!list_empty(&box->connected_phones)) {
-		phone = list_get_instance(box->connected_phones.next,
+		phone = list_get_instance(list_first(&box->connected_phones),
 		    phone_t, link);
 		if (SYNCH_FAILED(mutex_trylock(&phone->lock))) {
@@ -606,7 +609,7 @@
 	/* Wait for all answers to interrupted synchronous calls to arrive */
 	ipl_t ipl = interrupts_disable();
-	while (!list_empty(&TASK->sync_box_head)) {
-		answerbox_t *box = list_get_instance(TASK->sync_box_head.next,
-		    answerbox_t, sync_box_link);
+	while (!list_empty(&TASK->sync_boxes)) {
+		answerbox_t *box = list_get_instance(
+		    list_first(&TASK->sync_boxes), answerbox_t, sync_box_link);
 		
 		list_remove(&box->sync_box_link);
@@ -743,9 +746,6 @@
 #endif
 	
-	link_t *cur;
-	
 	printf(" --- incomming calls ---\n");
-	for (cur = task->answerbox.calls.next; cur != &task->answerbox.calls;
-	    cur = cur->next) {
+	list_foreach(task->answerbox.calls, cur) {
 		call_t *call = list_get_instance(cur, call_t, link);
 		
@@ -767,7 +767,5 @@
 	
 	printf(" --- dispatched calls ---\n");
-	for (cur = task->answerbox.dispatched_calls.next;
-	    cur != &task->answerbox.dispatched_calls;
-	    cur = cur->next) {
+	list_foreach(task->answerbox.dispatched_calls, cur) {
 		call_t *call = list_get_instance(cur, call_t, link);
 		
@@ -789,7 +787,5 @@
 	
 	printf(" --- incoming answers ---\n");
-	for (cur = task->answerbox.answers.next;
-	    cur != &task->answerbox.answers;
-	    cur = cur->next) {
+	list_foreach(task->answerbox.answers, cur) {
 		call_t *call = list_get_instance(cur, call_t, link);
 		
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -146,10 +146,9 @@
 call_t *get_call(sysarg_t callid)
 {
-	link_t *lst;
 	call_t *result = NULL;
 	
 	irq_spinlock_lock(&TASK->answerbox.lock, true);
-	for (lst = TASK->answerbox.dispatched_calls.next;
-	    lst != &TASK->answerbox.dispatched_calls; lst = lst->next) {
+	
+	list_foreach(TASK->answerbox.dispatched_calls, lst) {
 		call_t *call = list_get_instance(lst, call_t, link);
 		if ((sysarg_t) call == callid) {
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/ipc/irq.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -200,5 +200,5 @@
 	
 	hash_table_insert(&irq_uspace_hash_table, key, &irq->link);
-	list_append(&irq->notif_cfg.link, &box->irq_head);
+	list_append(&irq->notif_cfg.link, &box->irq_list);
 	
 	irq_spinlock_unlock(&box->irq_lock, false);
@@ -282,8 +282,8 @@
 	irq_spinlock_lock(&box->irq_lock, false);
 	
-	while (box->irq_head.next != &box->irq_head) {
+	while (!list_empty(&box->irq_list)) {
 		DEADLOCK_PROBE_INIT(p_irqlock);
 		
-		irq_t *irq = list_get_instance(box->irq_head.next, irq_t,
+		irq_t *irq = list_get_instance(list_first(&box->irq_list), irq_t,
 		    notif_cfg.link);
 		
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/mm/as.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -94,5 +94,5 @@
  *
  * This lock protects:
- * - inactive_as_with_asid_head list
+ * - inactive_as_with_asid_list
  * - as->asid for each as of the as_t type
  * - asids_allocated counter
@@ -105,5 +105,5 @@
  * that have valid ASID.
  */
-LIST_INITIALIZE(inactive_as_with_asid_head);
+LIST_INITIALIZE(inactive_as_with_asid_list);
 
 /** Kernel address space. */
@@ -235,8 +235,8 @@
 	bool cond = true;
 	while (cond) {
-		ASSERT(!list_empty(&as->as_area_btree.leaf_head));
+		ASSERT(!list_empty(&as->as_area_btree.leaf_list));
 		
 		btree_node_t *node =
-		    list_get_instance(as->as_area_btree.leaf_head.next,
+		    list_get_instance(list_first(&as->as_area_btree.leaf_list),
 		    btree_node_t, leaf_link);
 		
@@ -602,8 +602,8 @@
 		bool cond = true;
 		while (cond) {
-			ASSERT(!list_empty(&area->used_space.leaf_head));
+			ASSERT(!list_empty(&area->used_space.leaf_list));
 			
 			btree_node_t *node =
-			    list_get_instance(area->used_space.leaf_head.prev,
+			    list_get_instance(list_last(&area->used_space.leaf_list),
 			    btree_node_t, leaf_link);
 			
@@ -727,5 +727,4 @@
 	if (--sh_info->refcount == 0) {
 		dealloc = true;
-		link_t *cur;
 		
 		/*
@@ -733,6 +732,5 @@
 		 * reference from all frames found there.
 		 */
-		for (cur = sh_info->pagemap.leaf_head.next;
-		    cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
+		list_foreach(sh_info->pagemap.leaf_list, cur) {
 			btree_node_t *node
 			    = list_get_instance(cur, btree_node_t, leaf_link);
@@ -786,7 +784,5 @@
 	 * Visit only the pages mapped by used_space B+tree.
 	 */
-	link_t *cur;
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
+	list_foreach(area->used_space.leaf_list, cur) {
 		btree_node_t *node;
 		btree_key_t i;
@@ -1065,8 +1061,6 @@
 	 */
 	size_t used_pages = 0;
-	link_t *cur;
-	
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
+	
+	list_foreach(area->used_space.leaf_list, cur) {
 		btree_node_t *node
 		    = list_get_instance(cur, btree_node_t, leaf_link);
@@ -1094,6 +1088,5 @@
 	size_t frame_idx = 0;
 	
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
+	list_foreach(area->used_space.leaf_list, cur) {
 		btree_node_t *node = list_get_instance(cur, btree_node_t,
 		    leaf_link);
@@ -1147,6 +1140,5 @@
 	frame_idx = 0;
 	
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
+	list_foreach(area->used_space.leaf_list, cur) {
 		btree_node_t *node
 		    = list_get_instance(cur, btree_node_t, leaf_link);
@@ -1334,5 +1326,5 @@
 			
 			list_append(&old_as->inactive_as_with_asid_link,
-			    &inactive_as_with_asid_head);
+			    &inactive_as_with_asid_list);
 		}
 		
@@ -2027,8 +2019,8 @@
 	
 	/* Eventually check the addresses behind each area */
-	link_t *cur;
-	for (cur = AS->as_area_btree.leaf_head.next;
-	    (ret == 0) && (cur != &AS->as_area_btree.leaf_head);
-	    cur = cur->next) {
+	list_foreach(AS->as_area_btree.leaf_list, cur) {
+		if (ret != 0)
+			break;
+
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
@@ -2072,8 +2064,6 @@
 	
 	size_t area_cnt = 0;
-	link_t *cur;
-	
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
@@ -2088,6 +2078,5 @@
 	size_t area_idx = 0;
 	
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
@@ -2125,7 +2114,5 @@
 	
 	/* Print out info about address space areas */
-	link_t *cur;
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node
 		    = list_get_instance(cur, btree_node_t, leaf_link);
Index: kernel/generic/src/mm/backend_anon.c
===================================================================
--- kernel/generic/src/mm/backend_anon.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/mm/backend_anon.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -97,6 +97,4 @@
 void anon_share(as_area_t *area)
 {
-	link_t *cur;
-
 	ASSERT(mutex_locked(&area->as->lock));
 	ASSERT(mutex_locked(&area->lock));
@@ -106,6 +104,5 @@
 	 */
 	mutex_lock(&area->sh_info->lock);
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
+	list_foreach(area->used_space.leaf_list, cur) {
 		btree_node_t *node;
 		unsigned int i;
Index: kernel/generic/src/mm/backend_elf.c
===================================================================
--- kernel/generic/src/mm/backend_elf.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/mm/backend_elf.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -139,5 +139,5 @@
 	 */
 	if (area->flags & AS_AREA_WRITE) {
-		node = list_get_instance(area->used_space.leaf_head.next,
+		node = list_get_instance(list_first(&area->used_space.leaf_list),
 		    btree_node_t, leaf_link);
 	} else {
@@ -153,5 +153,5 @@
 	 */
 	mutex_lock(&area->sh_info->lock);
-	for (cur = &node->leaf_link; cur != &area->used_space.leaf_head;
+	for (cur = &node->leaf_link; cur != &area->used_space.leaf_list.head;
 	    cur = cur->next) {
 		unsigned int i;
Index: kernel/generic/src/mm/buddy.c
===================================================================
--- kernel/generic/src/mm/buddy.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/mm/buddy.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -82,5 +82,5 @@
 	 * Use memory after our own structure.
 	 */
-	b->order = (link_t *) (&b[1]);
+	b->order = (list_t *) (&b[1]);
 	
 	for (i = 0; i <= max_order; i++)
@@ -176,6 +176,6 @@
 	 * the request can be immediatelly satisfied.
 	 */
-	if (!list_empty(&b->order[i])) {
-		res = b->order[i].next;
+	res = list_first(&b->order[i]);
+	if (res != NULL) {
 		list_remove(res);
 		b->op->mark_busy(b, res);
Index: kernel/generic/src/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/mm/slab.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -317,6 +317,6 @@
 		spinlock_lock(&cache->slablock);
 	} else {
-		slab = list_get_instance(cache->partial_slabs.next, slab_t,
-		    link);
+		slab = list_get_instance(list_first(&cache->partial_slabs),
+		    slab_t, link);
 		list_remove(&slab->link);
 	}
@@ -360,7 +360,7 @@
 	if (!list_empty(&cache->magazines)) {
 		if (first)
-			cur = cache->magazines.next;
+			cur = list_first(&cache->magazines);
 		else
-			cur = cache->magazines.prev;
+			cur = list_last(&cache->magazines);
 		
 		mag = list_get_instance(cur, slab_magazine_t, link);
@@ -812,7 +812,5 @@
 	
 	size_t frames = 0;
-	link_t *cur;
-	for (cur = slab_cache_list.next; cur != &slab_cache_list;
-	    cur = cur->next) {
+	list_foreach(slab_cache_list, cur) {
 		slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
 		frames += _slab_reclaim(cache, flags);
@@ -861,9 +859,9 @@
 		link_t *cur;
 		size_t i;
-		for (i = 0, cur = slab_cache_list.next;
-		    (i < skip) && (cur != &slab_cache_list);
+		for (i = 0, cur = slab_cache_list.head.next;
+		    (i < skip) && (cur != &slab_cache_list.head);
 		    i++, cur = cur->next);
 		
-		if (cur == &slab_cache_list) {
+		if (cur == &slab_cache_list.head) {
 			irq_spinlock_unlock(&slab_cache_lock, true);
 			break;
@@ -940,7 +938,5 @@
 	irq_spinlock_lock(&slab_cache_lock, false);
 	
-	link_t *cur;
-	for (cur = slab_cache_list.next; cur != &slab_cache_list;
-	    cur = cur->next) {
+	list_foreach(slab_cache_list, cur) {
 		slab_cache_t *slab = list_get_instance(cur, slab_cache_t, link);
 		if ((slab->flags & SLAB_CACHE_MAGDEFERRED) !=
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/proc/scheduler.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -237,6 +237,6 @@
 		 * Take the first thread from the queue.
 		 */
-		thread_t *thread =
-		    list_get_instance(CPU->rq[i].rq_head.next, thread_t, rq_link);
+		thread_t *thread = list_get_instance(
+		    list_first(&CPU->rq[i].rq), thread_t, rq_link);
 		list_remove(&thread->rq_link);
 		
@@ -273,7 +273,7 @@
 static void relink_rq(int start)
 {
-	link_t head;
-	
-	list_initialize(&head);
+	list_t list;
+	
+	list_initialize(&list);
 	irq_spinlock_lock(&CPU->lock, false);
 	
@@ -284,5 +284,5 @@
 			
 			irq_spinlock_lock(&CPU->rq[i + 1].lock, false);
-			list_concat(&head, &CPU->rq[i + 1].rq_head);
+			list_concat(&list, &CPU->rq[i + 1].rq);
 			size_t n = CPU->rq[i + 1].n;
 			CPU->rq[i + 1].n = 0;
@@ -292,5 +292,5 @@
 			
 			irq_spinlock_lock(&CPU->rq[i].lock, false);
-			list_concat(&CPU->rq[i].rq_head, &head);
+			list_concat(&CPU->rq[i].rq, &list);
 			CPU->rq[i].n += n;
 			irq_spinlock_unlock(&CPU->rq[i].lock, false);
@@ -616,7 +616,7 @@
 			
 			/* Search rq from the back */
-			link_t *link = cpu->rq[rq].rq_head.prev;
-			
-			while (link != &(cpu->rq[rq].rq_head)) {
+			link_t *link = cpu->rq[rq].rq.head.prev;
+			
+			while (link != &(cpu->rq[rq].rq.head)) {
 				thread = (thread_t *) list_get_instance(link,
 				    thread_t, rq_link);
@@ -740,9 +740,7 @@
 			
 			printf("\trq[%u]: ", i);
-			link_t *cur;
-			for (cur = cpus[cpu].rq[i].rq_head.next;
-			    cur != &(cpus[cpu].rq[i].rq_head);
-			    cur = cur->next) {
-				thread_t *thread = list_get_instance(cur, thread_t, rq_link);
+			list_foreach(cpus[cpu].rq[i].rq, cur) {
+				thread_t *thread = list_get_instance(cur,
+				    thread_t, rq_link);
 				printf("%" PRIu64 "(%s) ", thread->tid,
 				    thread_states[thread->state]);
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/proc/task.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -155,6 +155,6 @@
 	mutex_initialize(&task->futexes_lock, MUTEX_PASSIVE);
 	
-	list_initialize(&task->th_head);
-	list_initialize(&task->sync_box_head);
+	list_initialize(&task->threads);
+	list_initialize(&task->sync_boxes);
 	
 	ipc_answerbox_init(&task->answerbox, task);
@@ -435,6 +435,5 @@
 	
 	/* Current values of threads */
-	link_t *cur;
-	for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
+	list_foreach(task->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		
@@ -468,6 +467,5 @@
 	 */
 	
-	link_t *cur;
-	for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
+	list_foreach(task->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		bool sleeping = false;
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/proc/thread.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -260,5 +260,5 @@
 	 */
 	
-	list_append(&thread->rq_link, &cpu->rq[i].rq_head);
+	list_append(&thread->rq_link, &cpu->rq[i].rq);
 	cpu->rq[i].n++;
 	irq_spinlock_unlock(&(cpu->rq[i].lock), true);
@@ -423,5 +423,5 @@
 		atomic_inc(&task->lifecount);
 	
-	list_append(&thread->th_link, &task->th_head);
+	list_append(&thread->th_link, &task->threads);
 	
 	irq_spinlock_pass(&task->lock, &threads_lock);
Index: kernel/generic/src/synch/futex.c
===================================================================
--- kernel/generic/src/synch/futex.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/synch/futex.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -272,11 +272,8 @@
 void futex_cleanup(void)
 {
-	link_t *cur;
-	
 	mutex_lock(&futex_ht_lock);
 	mutex_lock(&TASK->futexes_lock);
 
-	for (cur = TASK->futexes.leaf_head.next;
-	    cur != &TASK->futexes.leaf_head; cur = cur->next) {
+	list_foreach(TASK->futexes.leaf_list, cur) {
 		btree_node_t *node;
 		unsigned int i;
Index: kernel/generic/src/synch/waitq.c
===================================================================
--- kernel/generic/src/synch/waitq.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/synch/waitq.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -69,5 +69,5 @@
 {
 	irq_spinlock_initialize(&wq->lock, "wq.lock");
-	list_initialize(&wq->head);
+	list_initialize(&wq->sleepers);
 	wq->missed_wakeups = 0;
 }
@@ -196,6 +196,7 @@
 	irq_spinlock_lock(&wq->lock, true);
 	
-	if (!list_empty(&wq->head)) {
-		thread_t *thread = list_get_instance(wq->head.next, thread_t, wq_link);
+	if (!list_empty(&wq->sleepers)) {
+		thread_t *thread = list_get_instance(list_first(&wq->sleepers),
+		    thread_t, wq_link);
 		
 		irq_spinlock_lock(&thread->lock, false);
@@ -407,5 +408,5 @@
 	}
 	
-	list_append(&THREAD->wq_link, &wq->head);
+	list_append(&THREAD->wq_link, &wq->sleepers);
 	
 	/*
@@ -464,5 +465,5 @@
 	
 loop:
-	if (list_empty(&wq->head)) {
+	if (list_empty(&wq->sleepers)) {
 		wq->missed_wakeups++;
 		if ((count) && (mode == WAKEUP_ALL))
@@ -473,5 +474,6 @@
 	
 	count++;
-	thread_t *thread = list_get_instance(wq->head.next, thread_t, wq_link);
+	thread_t *thread = list_get_instance(list_first(&wq->sleepers),
+	    thread_t, wq_link);
 	
 	/*
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/sysinfo/stats.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -173,7 +173,5 @@
 	
 	/* Walk the B+ tree and count pages */
-	link_t *cur;
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
@@ -218,7 +216,5 @@
 	
 	/* Walk the B+ tree and count pages */
-	link_t *cur;
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
Index: kernel/generic/src/time/clock.c
===================================================================
--- kernel/generic/src/time/clock.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/time/clock.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -163,6 +163,7 @@
 		
 		link_t *cur;
-		while ((cur = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
-			timeout_t *timeout = list_get_instance(cur, timeout_t, link);
+		while ((cur = list_first(&CPU->timeout_active_list)) != NULL) {
+			timeout_t *timeout = list_get_instance(cur, timeout_t,
+			    link);
 			
 			irq_spinlock_lock(&timeout->lock, false);
Index: kernel/generic/src/time/delay.c
===================================================================
--- kernel/generic/src/time/delay.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/time/delay.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -64,3 +64,3 @@
 
 /** @}
-*/
+ */
Index: kernel/generic/src/time/timeout.c
===================================================================
--- kernel/generic/src/time/timeout.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/time/timeout.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -54,5 +54,5 @@
 {
 	irq_spinlock_initialize(&CPU->timeoutlock, "cpu.timeoutlock");
-	list_initialize(&CPU->timeout_active_head);
+	list_initialize(&CPU->timeout_active_list);
 }
 
@@ -119,6 +119,6 @@
 	timeout_t *target = NULL;
 	link_t *cur;
-	for (cur = CPU->timeout_active_head.next;
-	    cur != &CPU->timeout_active_head; cur = cur->next) {
+	for (cur = CPU->timeout_active_list.head.next;
+	    cur != &CPU->timeout_active_list.head; cur = cur->next) {
 		target = list_get_instance(cur, timeout_t, link);
 		irq_spinlock_lock(&target->lock, false);
@@ -135,5 +135,5 @@
 	/* Avoid using cur->prev directly */
 	link_t *prev = cur->prev;
-	list_prepend(&timeout->link, prev);
+	list_insert_after(&timeout->link, prev);
 	
 	/*
@@ -146,5 +146,5 @@
 	 * Decrease ticks of timeout's immediate succesor by timeout->ticks.
 	 */
-	if (cur != &CPU->timeout_active_head) {
+	if (cur != &CPU->timeout_active_list.head) {
 		irq_spinlock_lock(&target->lock, false);
 		target->ticks -= timeout->ticks;
@@ -184,9 +184,9 @@
 	/*
 	 * Now we know for sure that timeout hasn't been activated yet
-	 * and is lurking in timeout->cpu->timeout_active_head queue.
+	 * and is lurking in timeout->cpu->timeout_active_list.
 	 */
 	
 	link_t *cur = timeout->link.next;
-	if (cur != &timeout->cpu->timeout_active_head) {
+	if (cur != &timeout->cpu->timeout_active_list.head) {
 		timeout_t *tmp = list_get_instance(cur, timeout_t, link);
 		irq_spinlock_lock(&tmp->lock, false);
Index: kernel/generic/src/udebug/udebug.c
===================================================================
--- kernel/generic/src/udebug/udebug.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/udebug/udebug.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -406,6 +406,5 @@
 	
 	/* Finish debugging of all userspace threads */
-	link_t *cur;
-	for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
+	list_foreach(task->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		
Index: kernel/generic/src/udebug/udebug_ops.c
===================================================================
--- kernel/generic/src/udebug/udebug_ops.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ kernel/generic/src/udebug/udebug_ops.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -196,6 +196,5 @@
 	/* Set udebug.active on all of the task's userspace threads. */
 	
-	link_t *cur;
-	for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
+	list_foreach(TASK->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		
@@ -390,6 +389,5 @@
 	
 	/* FIXME: make sure the thread isn't past debug shutdown... */
-	link_t *cur;
-	for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
+	list_foreach(TASK->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -81,6 +81,4 @@
 	srv/fs/devfs \
 	srv/fs/ext2fs \
-	srv/hid/adb_mouse \
-	srv/hid/char_mouse \
 	srv/hid/s3c24xx_ts \
 	srv/hid/fb \
@@ -96,20 +94,20 @@
 	srv/net/tl/tcp \
 	srv/net/net \
-	drv/root \
-	drv/rootvirt \
-	drv/test1 \
-	drv/test2 \
-	drv/test3 \
-	drv/ehci_hcd \
-	drv/ohci \
-	drv/uhci_hcd \
-	drv/uhci_rhd \
-	drv/usbflbk \
-	drv/usbhid \
-	drv/usbhub \
-	drv/usbmast \
-	drv/usbmid \
-	drv/usbmouse \
-	drv/vhc
+	drv/infrastructure/root \
+	drv/infrastructure/rootvirt \
+	drv/test/test1 \
+	drv/test/test2 \
+	drv/test/test3 \
+	drv/bus/usb/ehci \
+	drv/bus/usb/ohci \
+	drv/bus/usb/uhci \
+	drv/bus/usb/uhcirh \
+	drv/bus/usb/usbflbk \
+	drv/bus/usb/usbhid \
+	drv/bus/usb/usbhub \
+	drv/bus/usb/usbmast \
+	drv/bus/usb/usbmid \
+	drv/bus/usb/usbmouse \
+	drv/bus/usb/vhc
 
 ifeq ($(CONFIG_BINUTILS),y)
@@ -134,8 +132,8 @@
 ifeq ($(UARCH),amd64)
 	DIRS += \
-		drv/rootpc \
-		drv/pciintel \
-		drv/isa \
-		drv/ns8250 \
+		drv/infrastructure/rootpc \
+		drv/bus/pci/pciintel \
+		drv/bus/isa \
+		drv/char/ns8250 \
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259
@@ -144,8 +142,8 @@
 ifeq ($(UARCH),ia32)
 	DIRS += \
-		drv/rootpc \
-		drv/pciintel \
-		drv/isa \
-		drv/ns8250 \
+		drv/infrastructure/rootpc \
+		drv/bus/pci/pciintel \
+		drv/bus/isa \
+		drv/char/ns8250 \
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259
@@ -153,5 +151,7 @@
 
 ifeq ($(UARCH),ppc32)
-	DIRS += srv/hw/bus/cuda_adb
+	DIRS += \
+		drv/infrastructure/rootmac \
+		srv/hw/bus/cuda_adb
 endif
 
Index: uspace/app/edit/sheet.c
===================================================================
--- uspace/app/edit/sheet.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/edit/sheet.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -75,5 +75,5 @@
 		return ENOMEM;
 
-	list_initialize(&sh->tags_head);
+	list_initialize(&sh->tags);
 
 	return EOK;
@@ -97,5 +97,4 @@
 	char *ipp;
 	size_t sz;
-	link_t *link;
 	tag_t *tag;
 	char *newp;
@@ -121,6 +120,5 @@
 	/* Adjust tags. */
 
-	link = sh->tags_head.next;
-	while (link != &sh->tags_head) {
+	list_foreach(sh->tags, link) {
 		tag = list_get_instance(link, tag_t, link);
 
@@ -129,6 +127,4 @@
 		else if (tag->b_off == pos->b_off && dir == dir_before)
 			tag->b_off += sz;
-
-		link = link->next;
 	}
 
@@ -150,5 +146,4 @@
 	char *spp;
 	size_t sz;
-	link_t *link;
 	tag_t *tag;
 	char *newp;
@@ -162,6 +157,5 @@
 
 	/* Adjust tags. */
-	link = sh->tags_head.next;
-	while (link != &sh->tags_head) {
+	list_foreach(sh->tags, link) {
 		tag = list_get_instance(link, tag_t, link);
 
@@ -170,6 +164,4 @@
 		else if (tag->b_off >= spos->b_off)
 			tag->b_off = spos->b_off;
-
-		link = link->next;
 	}
 
@@ -328,5 +320,5 @@
 	tag->b_off = pt->b_off;
 	tag->sh = sh;
-	list_append(&tag->link, &sh->tags_head);
+	list_append(&tag->link, &sh->tags);
 }
 
Index: uspace/app/edit/sheet.h
===================================================================
--- uspace/app/edit/sheet.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/edit/sheet.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -57,5 +57,5 @@
 	char *data;
 
-	link_t tags_head;
+	list_t tags;
 } sheet_t;
 
@@ -91,5 +91,5 @@
 	/* Note: This structure is opaque for the user. */
 
-	/** Link to list of all tags in the sheet (see sheet_t.tags_head) */
+	/** Link to list of all tags in the sheet (see sheet_t.tags) */
 	link_t link;
 	sheet_t *sh;
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/init/init.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -275,11 +275,9 @@
 	srv_start("/srv/i8042");
 	srv_start("/srv/s3c24ser");
-	srv_start("/srv/adb_ms");
-	srv_start("/srv/char_ms");
 	srv_start("/srv/s3c24ts");
 	
 	spawn("/srv/fb");
 	spawn("/srv/input");
-	console("hid_in/input");
+	console("hid/input");
 	
 	spawn("/srv/clip");
Index: uspace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/klog/klog.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -143,7 +143,7 @@
  * Receives kernel klog notifications.
  *
- * @param callid	IPC call ID
- * @param call		IPC call structure
- * @param arg		Local argument
+ * @param callid IPC call ID
+ * @param call   IPC call structure
+ * @param arg    Local argument
  *
  */
Index: uspace/app/mkbd/main.c
===================================================================
--- uspace/app/mkbd/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/mkbd/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -52,4 +52,6 @@
 #include <usb/hid/hiddescriptor.h>
 #include <usb/hid/usages/consumer.h>
+#include <io/console.h>
+#include <io/keycode.h>
 #include <assert.h>
 
@@ -166,4 +168,31 @@
 	
 	usb_hid_report_path_free(path);
+}
+
+static int wait_for_quit_fibril(void *arg)
+{
+	console_ctrl_t *con = console_init(stdin, stdout);
+
+	printf("Press <ESC> to quit the application.\n");
+
+	while (1) {
+		kbd_event_t ev;
+		bool ok = console_get_kbd_event(con, &ev);
+		if (!ok) {
+			printf("Connection with console broken: %s.\n",
+			    str_error(errno));
+			break;
+		}
+
+		if (ev.key == KC_ESCAPE) {
+			break;
+		}
+	}
+
+	console_done(con);
+
+	exit(0);
+
+	return EOK;
 }
 
@@ -242,4 +271,11 @@
 	}
 	
+	fid_t quit_fibril = fibril_create(wait_for_quit_fibril, NULL);
+	if (quit_fibril == 0) {
+		printf("Failed to start extra fibril.\n");
+		return -1;
+	}
+	fibril_add_ready(quit_fibril);
+
 	size_t actual_size;
 	int event_nr;
Index: uspace/app/ping/ping.c
===================================================================
--- uspace/app/ping/ping.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/ping/ping.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -341,5 +341,5 @@
 	    config.dest_str, config.size, config.size);
 	
-	int icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
+	int icmp_phone = icmp_connect_module();
 	if (icmp_phone < 0) {
 		fprintf(stderr, "%s: Unable to connect to ICMP service (%s)\n", NAME,
Index: uspace/app/sbi/src/compat.h
===================================================================
--- uspace/app/sbi/src/compat.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/sbi/src/compat.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -38,4 +38,7 @@
 #ifdef __HELENOS__
 
+#define list sbi_list
+#define list_t sbi_list_t
+
 /*
  * Avoid name conflicts with ADT library.
@@ -44,4 +47,6 @@
 #define list_prepend sbi_list_prepend
 #define list_remove sbi_list_remove
+#define list_first sbi_list_first
+#define list_last sbi_list_last
 
 #endif
Index: uspace/app/sbi/src/list_t.h
===================================================================
--- uspace/app/sbi/src/list_t.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/sbi/src/list_t.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -30,4 +30,6 @@
 #define LIST_T_H_
 
+#include "compat.h"
+
 typedef struct list_node {
 	struct list_node *prev, *next;
Index: uspace/app/tester/mm/common.c
===================================================================
--- uspace/app/tester/mm/common.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/tester/mm/common.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -73,10 +73,10 @@
 	link_t *link;
 	
-	while ((link = list_head(&mem_blocks)) != NULL) {
+	while ((link = list_first(&mem_blocks)) != NULL) {
 		mem_block_t *block = list_get_instance(link, mem_block_t, link);
 		free_block(block);
 	}
 	
-	while ((link = list_head(&mem_areas)) != NULL) {
+	while ((link = list_first(&mem_areas)) != NULL) {
 		mem_area_t *area = list_get_instance(link, mem_area_t, link);
 		unmap_area(area);
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/trace/trace.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -792,4 +792,5 @@
 	proto_register(SERVICE_VFS, p);
 
+#if 0
 	p = proto_new("console");
 
@@ -827,4 +828,5 @@
 	proto_console = p;
 	proto_register(SERVICE_CONSOLE, p);
+#endif
 }
 
Index: uspace/app/usbinfo/Makefile
===================================================================
--- uspace/app/usbinfo/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/usbinfo/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -31,4 +31,5 @@
 
 LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
 	$(LIBUSBDEV_PREFIX)/libusbdev.a \
 	$(LIBUSB_PREFIX)/libusb.a \
@@ -37,4 +38,5 @@
 	-I$(LIBUSB_PREFIX)/include \
 	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
 	-I$(LIBDRV_PREFIX)/include
 
@@ -43,4 +45,5 @@
 	dev.c \
 	dump.c \
+	hid.c \
 	info.c \
 	main.c
Index: uspace/app/usbinfo/dump.c
===================================================================
--- uspace/app/usbinfo/dump.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/usbinfo/dump.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -103,8 +103,5 @@
 void dump_match_ids(match_id_list_t *matches, const char *line_prefix)
 {
-	link_t *link;
-	for (link = matches->ids.next;
-	    link != &matches->ids;
-	    link = link->next) {
+	list_foreach(matches->ids, link) {
 		match_id_t *match = list_get_instance(link, match_id_t, link);
 
Index: uspace/app/usbinfo/hid.c
===================================================================
--- uspace/app/usbinfo/hid.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/app/usbinfo/hid.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,249 @@
+/*
+ * 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 usbinfo
+ * @{
+ */
+/**
+ * @file
+ * Dumping of HID-related properties.
+ */
+#include <stdio.h>
+#include <str_error.h>
+#include <usb/classes/classes.h>
+#include <usb/dev/request.h>
+#include <usb/hid/hidparser.h>
+#include <errno.h>
+#include "usbinfo.h"
+
+#define BYTES_PER_LINE 20
+
+typedef enum {
+	HID_DUMP_RAW,
+	HID_DUMP_USAGES
+} hid_dump_type_t;
+
+typedef struct {
+	usbinfo_device_t *dev;
+	hid_dump_type_t dump_type;
+	usb_standard_interface_descriptor_t *last_iface;
+} descriptor_walk_context_t;
+
+static bool is_descriptor_kind(uint8_t *d, usb_descriptor_type_t t)
+{
+	if (d == NULL) {
+		return false;
+	}
+	uint8_t size = d[0];
+	if (size <= 1) {
+		return false;
+	}
+	uint8_t type = d[1];
+	return type == t;
+}
+
+/** Dumps HID report in raw format.
+ *
+ * @param iface_no USB interface the report belongs to.
+ * @param report Report descriptor.
+ * @param size Size of the @p report in bytes.
+ */
+static void dump_hid_report_raw(int iface_no, uint8_t *report, size_t size)
+{
+	printf("%sHID report descriptor for interface %d", get_indent(0),
+	    iface_no);
+	for (size_t i = 0; i < size; i++) {
+		size_t line_idx = i % BYTES_PER_LINE;
+		if (line_idx == 0) {
+			printf("\n%s", get_indent(1));
+		}
+		printf("%02X", (int) report[i]);
+		if (line_idx + 1 < BYTES_PER_LINE) {
+			printf(" ");
+		}
+	}
+	printf("\n");
+}
+
+/** Dumps usages in HID report.
+ *
+ * @param iface_no USB interface the report belongs to.
+ * @param report Parsed report descriptor.
+ */
+static void dump_hid_report_usages(int iface_no, usb_hid_report_t *report)
+{
+	printf("%sParsed HID report descriptor for interface %d\n",
+	    get_indent(0), iface_no);
+	list_foreach(report->reports, report_it) {
+		usb_hid_report_description_t *description = list_get_instance(
+		    report_it, usb_hid_report_description_t, reports_link);
+		printf("%sReport %d (type %d)\n", get_indent(1),
+		    (int) description->report_id,
+		    (int) description->type);
+		list_foreach(description->report_items, item_it) {
+			usb_hid_report_field_t *field = list_get_instance(
+			    item_it, usb_hid_report_field_t, ritems_link);
+			printf("%sUsage page = 0x%04x    Usage = 0x%04x\n",
+			    get_indent(2),
+			    (int) field->usage_page, (int) field->usage);
+		}
+	}
+}
+
+/** Retrieves HID report from given USB device and dumps it.
+ *
+ * @param dump_type In which format to dump the report.
+ * @param ctrl_pipe Default control pipe to the device.
+ * @param iface_no Interface number.
+ * @param report_size Size of the report descriptor.
+ */
+static void retrieve_and_dump_hid_report(hid_dump_type_t dump_type,
+    usb_pipe_t *ctrl_pipe, uint8_t iface_no, size_t report_size)
+{
+	assert(report_size > 0);
+
+	uint8_t *raw_report = malloc(report_size);
+	if (raw_report == NULL) {
+		usb_log_warning(
+		    "Failed to allocate %zuB, skipping interface %d.\n",
+		    report_size, (int) iface_no);
+		return;
+	}
+
+	size_t actual_report_size;
+	int rc = usb_request_get_descriptor(ctrl_pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DESCTYPE_HID_REPORT, 0, iface_no,
+	    raw_report, report_size, &actual_report_size);
+	if (rc != EOK) {
+		usb_log_error("Failed to retrieve HID report descriptor: %s.\n",
+		    str_error(rc));
+		free(raw_report);
+		return;
+	}
+
+	usb_hid_report_t report;
+	rc = usb_hid_parse_report_descriptor(&report, raw_report, report_size);
+	if (rc != EOK) {
+		usb_log_error("Failed to part report descriptor: %s.\n",
+		    str_error(rc));
+	}
+
+	switch (dump_type) {
+	case HID_DUMP_RAW:
+		dump_hid_report_raw(iface_no, raw_report, report_size);
+		break;
+	case HID_DUMP_USAGES:
+		dump_hid_report_usages(iface_no, &report);
+		break;
+	default:
+		assert(false && "unreachable code apparently reached");
+	}
+
+	free(raw_report);
+	usb_hid_free_report(&report);
+}
+
+/** Callback for walking descriptor tree.
+ * This callback remembers current interface and dumps HID report after
+ * encountering HID descriptor.
+ * It dumps only the first report and it expects it to be a normal
+ * report, not a physical one.
+ *
+ * @param raw_descriptor Descriptor as a byte array.
+ * @param depth Descriptor tree depth (currently ignored).
+ * @param arg Custom argument, passed as descriptor_walk_context_t.
+ */
+static void descriptor_walk_callback(uint8_t *raw_descriptor,
+    size_t depth, void *arg)
+{
+	descriptor_walk_context_t *context = (descriptor_walk_context_t *) arg;
+
+	if (is_descriptor_kind(raw_descriptor, USB_DESCTYPE_INTERFACE)) {
+		context->last_iface
+		    = (usb_standard_interface_descriptor_t *) raw_descriptor;
+		return;
+	}
+
+	if (!is_descriptor_kind(raw_descriptor, USB_DESCTYPE_HID)) {
+		return;
+	}
+
+	if (context->last_iface == NULL) {
+		return;
+	}
+
+	usb_standard_hid_descriptor_t *hid_descr
+	    = (usb_standard_hid_descriptor_t *) raw_descriptor;
+
+	if (hid_descr->report_desc_info.type != USB_DESCTYPE_HID_REPORT) {
+		return;
+	}
+
+	size_t report_size = hid_descr->report_desc_info.length;
+
+	if (report_size == 0) {
+		return;
+	}
+
+	retrieve_and_dump_hid_report(context->dump_type,
+	    &context->dev->ctrl_pipe, context->last_iface->interface_number,
+	    report_size);
+}
+
+
+void dump_hidreport_raw(usbinfo_device_t *dev)
+{
+	descriptor_walk_context_t context = {
+		.dev = dev,
+		.dump_type = HID_DUMP_RAW,
+		.last_iface = NULL
+	};
+
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    descriptor_walk_callback, &context);
+}
+
+void dump_hidreport_usages(usbinfo_device_t *dev)
+{
+	descriptor_walk_context_t context = {
+		.dev = dev,
+		.dump_type = HID_DUMP_USAGES,
+		.last_iface = NULL
+	};
+
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    descriptor_walk_callback, &context);
+}
+
+/** @}
+ */
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/usbinfo/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -56,5 +56,7 @@
 	printf("Usage: %s [options] device [device [device [ ... ]]]\n",
 	    app_name);
-	printf(_INDENT "The device is a devman path to the device.\n");
+	printf(_INDENT "The device can be specified in two ways.\n");
+	printf(_INDENT "  o Using its devman path, e.g. /hw/pci0/.../usb00_a1.\n");
+	printf(_INDENT "  o Or using BUS.ADDR numbers as printed by lsusb.\n");
 
 	_OPTION("-h --help", "Print this help and exit.");
@@ -65,4 +67,6 @@
 	_OPTION("-s --strings", "Try to print all string descriptors.");
 	_OPTION("-S --status", "Get status of the device.");
+	_OPTION("-r --hid-report", "Dump HID report descriptor.");
+	_OPTION("-r --hid-report-usages", "Dump usages of HID report.");
 
 	printf("\n");
@@ -82,7 +86,9 @@
 	{"strings", no_argument, NULL, 's'},
 	{"status", no_argument, NULL, 'S'},
+	{"hid-report", no_argument, NULL, 'r'},
+	{"hid-report-usages", no_argument, NULL, 'R'},
 	{0, 0, NULL, 0}
 };
-static const char *short_options = "himtTsS";
+static const char *short_options = "himtTsSrR";
 
 static usbinfo_action_t actions[] = {
@@ -115,4 +121,14 @@
 		.opt = 'S',
 		.action = dump_status,
+		.active = false
+	},
+	{
+		.opt = 'r',
+		.action = dump_hidreport_raw,
+		.active = false
+	},
+	{
+		.opt = 'R',
+		.action = dump_hidreport_usages,
 		.active = false
 	},
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/usbinfo/usbinfo.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -85,4 +85,6 @@
 void dump_strings(usbinfo_device_t *);
 void dump_status(usbinfo_device_t *);
+void dump_hidreport_raw(usbinfo_device_t *);
+void dump_hidreport_usages(usbinfo_device_t *);
 
 
Index: uspace/app/vuhid/Makefile
===================================================================
--- uspace/app/vuhid/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/app/vuhid/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -36,5 +36,6 @@
 	$(LIBUSBHID_PREFIX)/libusbhid.a \
 	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
 EXTRA_CFLAGS = \
 	-I$(LIBUSB_PREFIX)/include \
Index: uspace/drv/bus/isa/Makefile
===================================================================
--- uspace/drv/bus/isa/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/isa/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = isa
+
+SOURCES = \
+	isa.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/isa/isa.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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.
+ */
+
+/**
+ * @defgroup isa ISA bus driver.
+ * @brief HelenOS ISA bus driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <str_error.h>
+#include <ctype.h>
+#include <macros.h>
+#include <malloc.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <ops/hw_res.h>
+
+#include <devman.h>
+#include <ipc/devman.h>
+#include <device/hw_res.h>
+
+#define NAME "isa"
+#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
+
+/** Obtain soft-state pointer from function node pointer */
+#define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
+
+#define ISA_MAX_HW_RES 4
+
+typedef struct isa_fun {
+	ddf_fun_t *fnode;
+	hw_resource_list_t hw_resources;
+} isa_fun_t;
+
+static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
+{
+	isa_fun_t *fun = ISA_FUN(fnode);
+	assert(fun != NULL);
+
+	return &fun->hw_resources;
+}
+
+static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
+{
+	/* TODO */
+
+	return false;
+}
+
+static hw_res_ops_t isa_fun_hw_res_ops = {
+	&isa_get_fun_resources,
+	&isa_enable_fun_interrupt
+};
+
+static ddf_dev_ops_t isa_fun_ops;
+
+static int isa_add_device(ddf_dev_t *dev);
+
+/** The isa device driver's standard operations */
+static driver_ops_t isa_ops = {
+	.add_device = &isa_add_device
+};
+
+/** The isa device driver structure. */
+static driver_t isa_driver = {
+	.name = NAME,
+	.driver_ops = &isa_ops
+};
+
+static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
+{
+	isa_fun_t *fun = calloc(1, sizeof(isa_fun_t));
+	if (fun == NULL)
+		return NULL;
+
+	ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL) {
+		free(fun);
+		return NULL;
+	}
+
+	fun->fnode = fnode;
+	fnode->driver_data = fun;
+	return fun;
+}
+
+static char *fun_conf_read(const char *conf_path)
+{
+	bool suc = false;
+	char *buf = NULL;
+	bool opened = false;
+	int fd;
+	size_t len = 0;
+
+	fd = open(conf_path, O_RDONLY);
+	if (fd < 0) {
+		ddf_msg(LVL_ERROR, "Unable to open %s", conf_path);
+		goto cleanup;
+	}
+
+	opened = true;
+
+	len = lseek(fd, 0, SEEK_END);
+	lseek(fd, 0, SEEK_SET);
+	if (len == 0) {
+		ddf_msg(LVL_ERROR, "Configuration file '%s' is empty.",
+		    conf_path);
+		goto cleanup;
+	}
+
+	buf = malloc(len + 1);
+	if (buf == NULL) {
+		ddf_msg(LVL_ERROR, "Memory allocation failed.");
+		goto cleanup;
+	}
+
+	if (0 >= read(fd, buf, len)) {
+		ddf_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
+		goto cleanup;
+	}
+
+	buf[len] = 0;
+
+	suc = true;
+
+cleanup:
+	if (!suc && buf != NULL) {
+		free(buf);
+		buf = NULL;
+	}
+
+	if (opened)
+		close(fd);
+
+	return buf;
+}
+
+static char *str_get_line(char *str, char **next)
+{
+	char *line = str;
+
+	if (str == NULL) {
+		*next = NULL;
+		return NULL;
+	}
+
+	while (*str != '\0' && *str != '\n') {
+		str++;
+	}
+
+	if (*str != '\0') {
+		*next = str + 1;
+	} else {
+		*next = NULL;
+	}
+
+	*str = '\0';
+	return line;
+}
+
+static bool line_empty(const char *line)
+{
+	while (line != NULL && *line != 0) {
+		if (!isspace(*line))
+			return false;
+		line++;
+	}
+
+	return true;
+}
+
+static char *get_device_name(char *line)
+{
+	/* Skip leading spaces. */
+	while (*line != '\0' && isspace(*line)) {
+		line++;
+	}
+
+	/* Get the name part of the rest of the line. */
+	strtok(line, ":");
+
+	/* Allocate output buffer. */
+	size_t size = str_size(line) + 1;
+	char *name = malloc(size);
+
+	if (name != NULL) {
+		/* Copy the result to the output buffer. */
+		str_cpy(name, size, line);
+	}
+
+	return name;
+}
+
+static inline char *skip_spaces(char *line)
+{
+	/* Skip leading spaces. */
+	while (*line != '\0' && isspace(*line))
+		line++;
+
+	return line;
+}
+
+static void isa_fun_set_irq(isa_fun_t *fun, int irq)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
+
+	if (count < ISA_MAX_HW_RES) {
+		resources[count].type = INTERRUPT;
+		resources[count].res.interrupt.irq = irq;
+
+		fun->hw_resources.count++;
+
+		ddf_msg(LVL_NOTE, "Added irq 0x%x to function %s", irq,
+		    fun->fnode->name);
+	}
+}
+
+static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
+
+	if (count < ISA_MAX_HW_RES) {
+		resources[count].type = IO_RANGE;
+		resources[count].res.io_range.address = addr;
+		resources[count].res.io_range.size = len;
+		resources[count].res.io_range.endianness = LITTLE_ENDIAN;
+
+		fun->hw_resources.count++;
+
+		ddf_msg(LVL_NOTE, "Added io range (addr=0x%x, size=0x%x) to "
+		    "function %s", (unsigned int) addr, (unsigned int) len,
+		    fun->fnode->name);
+	}
+}
+
+static void fun_parse_irq(isa_fun_t *fun, char *val)
+{
+	int irq = 0;
+	char *end = NULL;
+
+	val = skip_spaces(val);
+	irq = (int)strtol(val, &end, 0x10);
+
+	if (val != end)
+		isa_fun_set_irq(fun, irq);
+}
+
+static void fun_parse_io_range(isa_fun_t *fun, char *val)
+{
+	size_t addr, len;
+	char *end = NULL;
+
+	val = skip_spaces(val);
+	addr = strtol(val, &end, 0x10);
+
+	if (val == end)
+		return;
+
+	val = skip_spaces(end);
+	len = strtol(val, &end, 0x10);
+
+	if (val == end)
+		return;
+
+	isa_fun_set_io_range(fun, addr, len);
+}
+
+static void get_match_id(char **id, char *val)
+{
+	char *end = val;
+
+	while (!isspace(*end))
+		end++;
+
+	size_t size = end - val + 1;
+	*id = (char *)malloc(size);
+	str_cpy(*id, size, val);
+}
+
+static void fun_parse_match_id(isa_fun_t *fun, char *val)
+{
+	char *id = NULL;
+	int score = 0;
+	char *end = NULL;
+	int rc;
+
+	val = skip_spaces(val);
+
+	score = (int)strtol(val, &end, 10);
+	if (val == end) {
+		ddf_msg(LVL_ERROR, "Cannot read match score for function "
+		    "%s.", fun->fnode->name);
+		return;
+	}
+
+	val = skip_spaces(end);
+	get_match_id(&id, val);
+	if (id == NULL) {
+		ddf_msg(LVL_ERROR, "Cannot read match ID for function %s.",
+		    fun->fnode->name);
+		return;
+	}
+
+	ddf_msg(LVL_DEBUG, "Adding match id '%s' with score %d to "
+	    "function %s", id, score, fun->fnode->name);
+
+	rc = ddf_fun_add_match_id(fun->fnode, id, score);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
+		    str_error(rc));
+	}
+}
+
+static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
+    void (*read_fn)(isa_fun_t *, char *))
+{
+	size_t proplen = str_size(prop);
+
+	if (str_lcmp(line, prop, proplen) == 0) {
+		line += proplen;
+		line = skip_spaces(line);
+		(*read_fn)(fun, line);
+
+		return true;
+	}
+
+	return false;
+}
+
+static void fun_prop_parse(isa_fun_t *fun, char *line)
+{
+	/* Skip leading spaces. */
+	line = skip_spaces(line);
+
+	if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
+	    !prop_parse(fun, line, "irq", &fun_parse_irq) &&
+	    !prop_parse(fun, line, "match", &fun_parse_match_id)) {
+
+		ddf_msg(LVL_ERROR, "Undefined device property at line '%s'",
+		    line);
+	}
+}
+
+static void fun_hw_res_alloc(isa_fun_t *fun)
+{
+	fun->hw_resources.resources = 
+	    (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
+}
+
+static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
+{
+	char *line;
+	char *fun_name = NULL;
+
+	/* Skip empty lines. */
+	while (true) {
+		line = str_get_line(fun_conf, &fun_conf);
+
+		if (line == NULL) {
+			/* no more lines */
+			return NULL;
+		}
+
+		if (!line_empty(line))
+			break;
+	}
+
+	/* Get device name. */
+	fun_name = get_device_name(line);
+	if (fun_name == NULL)
+		return NULL;
+
+	isa_fun_t *fun = isa_fun_create(dev, fun_name);
+	if (fun == NULL) {
+		free(fun_name);
+		return NULL;
+	}
+
+	/* Allocate buffer for the list of hardware resources of the device. */
+	fun_hw_res_alloc(fun);
+
+	/* Get properties of the device (match ids, irq and io range). */
+	while (true) {
+		line = str_get_line(fun_conf, &fun_conf);
+
+		if (line_empty(line)) {
+			/* no more device properties */
+			break;
+		}
+
+		/*
+		 * Get the device's property from the configuration line
+		 * and store it in the device structure.
+		 */
+		fun_prop_parse(fun, line);
+	}
+
+	/* Set device operations to the device. */
+	fun->fnode->ops = &isa_fun_ops;
+
+	ddf_msg(LVL_DEBUG, "Binding function %s.", fun->fnode->name);
+
+	/* XXX Handle error */
+	(void) ddf_fun_bind(fun->fnode);
+
+	return fun_conf;
+}
+
+static void fun_conf_parse(char *conf, ddf_dev_t *dev)
+{
+	while (conf != NULL && *conf != '\0') {
+		conf = isa_fun_read_info(conf, dev);
+	}
+}
+
+static void isa_functions_add(ddf_dev_t *dev)
+{
+	char *fun_conf;
+
+	fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
+	if (fun_conf != NULL) {
+		fun_conf_parse(fun_conf, dev);
+		free(fun_conf);
+	}
+}
+
+static int isa_add_device(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d",
+	    (int) dev->handle);
+
+	/* Make the bus device more visible. Does not do anything. */
+	ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
+
+	ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
+	if (ctl == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating control function.");
+		return EXDEV;
+	}
+
+	if (ddf_fun_bind(ctl) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding control function.");
+		return EXDEV;
+	}
+
+	/* Add functions as specified in the configuration file. */
+	isa_functions_add(dev);
+	ddf_msg(LVL_NOTE, "Finished enumerating legacy functions");
+
+	return EOK;
+}
+
+static void isa_init() 
+{
+	ddf_log_init(NAME, LVL_ERROR);
+	isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS ISA bus driver\n");
+	isa_init();
+	return ddf_driver_main(&isa_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/isa/isa.dev	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,15 @@
+com1:
+	match 100 isa/ns8250
+	irq 4
+	io_range 3f8 8
+
+com2:
+	match 100 isa/ns8250
+	irq 3
+	io_range 2f8 8
+
+keyboard:
+	match 100 isa/keyboard
+	irq 1
+	io_range 060 10
+	
Index: uspace/drv/bus/isa/isa.ma
===================================================================
--- uspace/drv/bus/isa/isa.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/isa/isa.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+9 	pci/ven=8086&dev=7000
Index: uspace/drv/bus/pci/pciintel/Makefile
===================================================================
--- uspace/drv/bus/pci/pciintel/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/pci/pciintel/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = pciintel
+
+SOURCES = \
+	pci.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,759 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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.
+ */
+
+/**
+ * @defgroup pciintel pci bus driver for intel method 1.
+ * @brief HelenOS root pci bus driver for intel method 1.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+#include <str_error.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <devman.h>
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+#include <ipc/irc.h>
+#include <ns.h>
+#include <ipc/services.h>
+#include <sysinfo.h>
+#include <ops/hw_res.h>
+#include <device/hw_res.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+#define NAME "pciintel"
+
+#define CONF_ADDR(bus, dev, fn, reg) \
+	((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
+
+/** Obtain PCI function soft-state from DDF function node */
+#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
+
+/** Obtain PCI bus soft-state from DDF device node */
+#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
+
+/** Obtain PCI bus soft-state from function soft-state */
+#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
+
+static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
+{
+	pci_fun_t *fun = PCI_FUN(fnode);
+	
+	if (fun == NULL)
+		return NULL;
+	return &fun->hw_resources;
+}
+
+static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
+{
+	/* This is an old ugly way, copied from ne2000 driver */
+	assert(fnode);
+	pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
+	
+	sysarg_t apic;
+	sysarg_t i8259;
+	
+	async_sess_t *irc_sess = NULL;
+	
+	if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
+	    || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
+		irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+		    SERVICE_IRC, 0, 0);
+	}
+	
+	if (!irc_sess)
+		return false;
+	
+	size_t i = 0;
+	hw_resource_list_t *res = &dev_data->hw_resources;
+	for (; i < res->count; i++) {
+		if (res->resources[i].type == INTERRUPT) {
+			const int irq = res->resources[i].res.interrupt.irq;
+			
+			async_exch_t *exch = async_exchange_begin(irc_sess);
+			const int rc =
+			    async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
+			async_exchange_end(exch);
+			
+			if (rc != EOK) {
+				async_hangup(irc_sess);
+				return false;
+			}
+		}
+	}
+	
+	async_hangup(irc_sess);
+	return true;
+}
+
+static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address,
+    uint32_t data)
+{
+	if (address > 252)
+		return EINVAL;
+	pci_conf_write_32(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_write_16(
+    ddf_fun_t *fun, uint32_t address, uint16_t data)
+{
+	if (address > 254)
+		return EINVAL;
+	pci_conf_write_16(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_write_8(
+    ddf_fun_t *fun, uint32_t address, uint8_t data)
+{
+	if (address > 255)
+		return EINVAL;
+	pci_conf_write_8(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_read_32(
+    ddf_fun_t *fun, uint32_t address, uint32_t *data)
+{
+	if (address > 252)
+		return EINVAL;
+	*data = pci_conf_read_32(PCI_FUN(fun), address);
+	return EOK;
+}
+
+static int pci_config_space_read_16(
+    ddf_fun_t *fun, uint32_t address, uint16_t *data)
+{
+	if (address > 254)
+		return EINVAL;
+	*data = pci_conf_read_16(PCI_FUN(fun), address);
+	return EOK;
+}
+
+static int pci_config_space_read_8(
+    ddf_fun_t *fun, uint32_t address, uint8_t *data)
+{
+	if (address > 255)
+		return EINVAL;
+	*data = pci_conf_read_8(PCI_FUN(fun), address);
+	return EOK;
+}
+
+static hw_res_ops_t pciintel_hw_res_ops = {
+	&pciintel_get_resources,
+	&pciintel_enable_interrupt
+};
+
+static pci_dev_iface_t pci_dev_ops = {
+	.config_space_read_8 = &pci_config_space_read_8,
+	.config_space_read_16 = &pci_config_space_read_16,
+	.config_space_read_32 = &pci_config_space_read_32,
+	.config_space_write_8 = &pci_config_space_write_8,
+	.config_space_write_16 = &pci_config_space_write_16,
+	.config_space_write_32 = &pci_config_space_write_32
+};
+
+static ddf_dev_ops_t pci_fun_ops = {
+	.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
+	.interfaces[PCI_DEV_IFACE] = &pci_dev_ops
+};
+
+static int pci_add_device(ddf_dev_t *);
+
+/** PCI bus driver standard operations */
+static driver_ops_t pci_ops = {
+	.add_device = &pci_add_device
+};
+
+/** PCI bus driver structure */
+static driver_t pci_driver = {
+	.name = NAME,
+	.driver_ops = &pci_ops
+};
+
+static pci_bus_t *pci_bus_new(void)
+{
+	pci_bus_t *bus;
+	
+	bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));
+	if (bus == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&bus->conf_mutex);
+	return bus;
+}
+
+static void pci_bus_delete(pci_bus_t *bus)
+{
+	assert(bus != NULL);
+	free(bus);
+}
+
+static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
+{
+	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	
+	fibril_mutex_lock(&bus->conf_mutex);
+	
+	uint32_t conf_addr;
+	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	void *addr = bus->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus->conf_addr_port, conf_addr);
+	
+	switch (len) {
+	case 1:
+		buf[0] = pio_read_8(addr);
+		break;
+	case 2:
+		((uint16_t *) buf)[0] = pio_read_16(addr);
+		break;
+	case 4:
+		((uint32_t *) buf)[0] = pio_read_32(addr);
+		break;
+	}
+	
+	fibril_mutex_unlock(&bus->conf_mutex);
+}
+
+static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
+{
+	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	
+	fibril_mutex_lock(&bus->conf_mutex);
+	
+	uint32_t conf_addr;
+	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	void *addr = bus->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus->conf_addr_port, conf_addr);
+	
+	switch (len) {
+	case 1:
+		pio_write_8(addr, buf[0]);
+		break;
+	case 2:
+		pio_write_16(addr, ((uint16_t *) buf)[0]);
+		break;
+	case 4:
+		pio_write_32(addr, ((uint32_t *) buf)[0]);
+		break;
+	}
+	
+	fibril_mutex_unlock(&bus->conf_mutex);
+}
+
+uint8_t pci_conf_read_8(pci_fun_t *fun, int reg)
+{
+	uint8_t res;
+	pci_conf_read(fun, reg, &res, 1);
+	return res;
+}
+
+uint16_t pci_conf_read_16(pci_fun_t *fun, int reg)
+{
+	uint16_t res;
+	pci_conf_read(fun, reg, (uint8_t *) &res, 2);
+	return res;
+}
+
+uint32_t pci_conf_read_32(pci_fun_t *fun, int reg)
+{
+	uint32_t res;
+	pci_conf_read(fun, reg, (uint8_t *) &res, 4);
+	return res;
+}
+
+void pci_conf_write_8(pci_fun_t *fun, int reg, uint8_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 1);
+}
+
+void pci_conf_write_16(pci_fun_t *fun, int reg, uint16_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 2);
+}
+
+void pci_conf_write_32(pci_fun_t *fun, int reg, uint32_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 4);
+}
+
+void pci_fun_create_match_ids(pci_fun_t *fun)
+{
+	char *match_id_str;
+	int rc;
+	
+	asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
+	    fun->vendor_id, fun->device_id);
+
+	if (match_id_str == NULL) {
+		ddf_msg(LVL_ERROR, "Out of memory creating match ID.");
+		return;
+	}
+
+	rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
+		    str_error(rc));
+	}
+	
+	/* TODO add more ids (with subsys ids, using class id etc.) */
+}
+
+void pci_add_range(pci_fun_t *fun, uint64_t range_addr, size_t range_size,
+    bool io)
+{
+	hw_resource_list_t *hw_res_list = &fun->hw_resources;
+	hw_resource_t *hw_resources =  hw_res_list->resources;
+	size_t count = hw_res_list->count;
+	
+	assert(hw_resources != NULL);
+	assert(count < PCI_MAX_HW_RES);
+	
+	if (io) {
+		hw_resources[count].type = IO_RANGE;
+		hw_resources[count].res.io_range.address = range_addr;
+		hw_resources[count].res.io_range.size = range_size;
+		hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
+	} else {
+		hw_resources[count].type = MEM_RANGE;
+		hw_resources[count].res.mem_range.address = range_addr;
+		hw_resources[count].res.mem_range.size = range_size;
+		hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
+	}
+	
+	hw_res_list->count++;
+}
+
+/** Read the base address register (BAR) of the device and if it contains valid
+ * address add it to the devices hw resource list.
+ *
+ * @param fun	PCI function
+ * @param addr	The address of the BAR in the PCI configuration address space of
+ *		the device
+ * @return	The addr the address of the BAR which should be read next
+ */
+int pci_read_bar(pci_fun_t *fun, int addr)
+{
+	/* Value of the BAR */
+	uint32_t val, mask;
+	/* IO space address */
+	bool io;
+	/* 64-bit wide address */
+	bool addrw64;
+	
+	/* Size of the io or memory range specified by the BAR */
+	size_t range_size;
+	/* Beginning of the io or memory range specified by the BAR */
+	uint64_t range_addr;
+	
+	/* Get the value of the BAR. */
+	val = pci_conf_read_32(fun, addr);
+
+#define IO_MASK  (~0x3)
+#define MEM_MASK (~0xf)
+	
+	io = (bool) (val & 1);
+	if (io) {
+		addrw64 = false;
+		mask = IO_MASK;
+	} else {
+		mask = MEM_MASK;
+		switch ((val >> 1) & 3) {
+		case 0:
+			addrw64 = false;
+			break;
+		case 2:
+			addrw64 = true;
+			break;
+		default:
+			/* reserved, go to the next BAR */
+			return addr + 4;
+		}
+	}
+	
+	/* Get the address mask. */
+	pci_conf_write_32(fun, addr, 0xffffffff);
+	mask &= pci_conf_read_32(fun, addr);
+	
+	/* Restore the original value. */
+	pci_conf_write_32(fun, addr, val);
+	val = pci_conf_read_32(fun, addr);
+	
+	range_size = pci_bar_mask_to_size(mask);
+	
+	if (addrw64) {
+		range_addr = ((uint64_t)pci_conf_read_32(fun, addr + 4) << 32) |
+		    (val & 0xfffffff0);
+	} else {
+		range_addr = (val & 0xfffffff0);
+	}
+	
+	if (range_addr != 0) {
+		ddf_msg(LVL_DEBUG, "Function %s : address = %" PRIx64
+		    ", size = %x", fun->fnode->name, range_addr,
+		    (unsigned int) range_size);
+	}
+	
+	pci_add_range(fun, range_addr, range_size, io);
+	
+	if (addrw64)
+		return addr + 8;
+	
+	return addr + 4;
+}
+
+void pci_add_interrupt(pci_fun_t *fun, int irq)
+{
+	hw_resource_list_t *hw_res_list = &fun->hw_resources;
+	hw_resource_t *hw_resources = hw_res_list->resources;
+	size_t count = hw_res_list->count;
+	
+	assert(NULL != hw_resources);
+	assert(count < PCI_MAX_HW_RES);
+	
+	hw_resources[count].type = INTERRUPT;
+	hw_resources[count].res.interrupt.irq = irq;
+	
+	hw_res_list->count++;
+	
+	ddf_msg(LVL_NOTE, "Function %s uses irq %x.", fun->fnode->name, irq);
+}
+
+void pci_read_interrupt(pci_fun_t *fun)
+{
+	uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
+	if (irq != 0xff)
+		pci_add_interrupt(fun, irq);
+}
+
+/** Enumerate (recursively) and register the devices connected to a pci bus.
+ *
+ * @param bus		Host-to-PCI bridge
+ * @param bus_num	Bus number
+ */
+void pci_bus_scan(pci_bus_t *bus, int bus_num) 
+{
+	ddf_fun_t *fnode;
+	pci_fun_t *fun;
+	
+	int child_bus = 0;
+	int dnum, fnum;
+	bool multi;
+	uint8_t header_type;
+	
+	fun = pci_fun_new(bus);
+	
+	for (dnum = 0; dnum < 32; dnum++) {
+		multi = true;
+		for (fnum = 0; multi && fnum < 8; fnum++) {
+			pci_fun_init(fun, bus_num, dnum, fnum);
+			fun->vendor_id = pci_conf_read_16(fun,
+			    PCI_VENDOR_ID);
+			fun->device_id = pci_conf_read_16(fun,
+			    PCI_DEVICE_ID);
+			if (fun->vendor_id == 0xffff) {
+				/*
+				 * The device is not present, go on scanning the
+				 * bus.
+				 */
+				if (fnum == 0)
+					break;
+				else
+					continue;
+			}
+			
+			header_type = pci_conf_read_8(fun, PCI_HEADER_TYPE);
+			if (fnum == 0) {
+				/* Is the device multifunction? */
+				multi = header_type >> 7;
+			}
+			/* Clear the multifunction bit. */
+			header_type = header_type & 0x7F;
+			
+			char *fun_name = pci_fun_create_name(fun);
+			if (fun_name == NULL) {
+				ddf_msg(LVL_ERROR, "Out of memory.");
+				return;
+			}
+			
+			fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
+			if (fnode == NULL) {
+				ddf_msg(LVL_ERROR, "Failed creating function.");
+				return;
+			}
+			
+			free(fun_name);
+			fun->fnode = fnode;
+			
+			pci_alloc_resource_list(fun);
+			pci_read_bars(fun);
+			pci_read_interrupt(fun);
+			
+			fnode->ops = &pci_fun_ops;
+			fnode->driver_data = fun;
+			
+			ddf_msg(LVL_DEBUG, "Adding new function %s.",
+			    fnode->name);
+			
+			pci_fun_create_match_ids(fun);
+			
+			if (ddf_fun_bind(fnode) != EOK) {
+				pci_clean_resource_list(fun);
+				clean_match_ids(&fnode->match_ids);
+				free((char *) fnode->name);
+				fnode->name = NULL;
+				continue;
+			}
+			
+			if (header_type == PCI_HEADER_TYPE_BRIDGE ||
+			    header_type == PCI_HEADER_TYPE_CARDBUS) {
+				child_bus = pci_conf_read_8(fun,
+				    PCI_BRIDGE_SEC_BUS_NUM);
+				ddf_msg(LVL_DEBUG, "Device is pci-to-pci "
+				    "bridge, secondary bus number = %d.",
+				    bus_num);
+				if (child_bus > bus_num)
+					pci_bus_scan(bus, child_bus);
+			}
+			
+			fun = pci_fun_new(bus);
+		}
+	}
+	
+	if (fun->vendor_id == 0xffff) {
+		/* Free the auxiliary function structure. */
+		pci_fun_delete(fun);
+	}
+}
+
+static int pci_add_device(ddf_dev_t *dnode)
+{
+	pci_bus_t *bus = NULL;
+	ddf_fun_t *ctl = NULL;
+	bool got_res = false;
+	int rc;
+	
+	ddf_msg(LVL_DEBUG, "pci_add_device");
+	dnode->parent_sess = NULL;
+	
+	bus = pci_bus_new();
+	if (bus == NULL) {
+		ddf_msg(LVL_ERROR, "pci_add_device allocation failed.");
+		rc = ENOMEM;
+		goto fail;
+	}
+	bus->dnode = dnode;
+	dnode->driver_data = bus;
+	
+	dnode->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    dnode->handle, IPC_FLAG_BLOCKING);
+	if (!dnode->parent_sess) {
+		ddf_msg(LVL_ERROR, "pci_add_device failed to connect to the "
+		    "parent driver.");
+		rc = ENOENT;
+		goto fail;
+	}
+	
+	hw_resource_list_t hw_resources;
+	
+	rc = hw_res_get_resource_list(dnode->parent_sess, &hw_resources);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "pci_add_device failed to get hw resources "
+		    "for the device.");
+		goto fail;
+	}
+	got_res = true;
+	
+	ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".",
+	    hw_resources.resources[0].res.io_range.address);
+	
+	assert(hw_resources.count > 0);
+	assert(hw_resources.resources[0].type == IO_RANGE);
+	assert(hw_resources.resources[0].res.io_range.size == 8);
+	
+	bus->conf_io_addr =
+	    (uint32_t) hw_resources.resources[0].res.io_range.address;
+	
+	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
+	    &bus->conf_addr_port)) {
+		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
+	bus->conf_data_port = (char *) bus->conf_addr_port + 4;
+	
+	/* Make the bus device more visible. It has no use yet. */
+	ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
+	
+	ctl = ddf_fun_create(bus->dnode, fun_exposed, "ctl");
+	if (ctl == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating control function.");
+		rc = ENOMEM;
+		goto fail;
+	}
+	
+	rc = ddf_fun_bind(ctl);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding control function.");
+		goto fail;
+	}
+	
+	/* Enumerate functions. */
+	ddf_msg(LVL_DEBUG, "Scanning the bus");
+	pci_bus_scan(bus, 0);
+	
+	hw_res_clean_resource_list(&hw_resources);
+	
+	return EOK;
+	
+fail:
+	if (bus != NULL)
+		pci_bus_delete(bus);
+	
+	if (dnode->parent_sess)
+		async_hangup(dnode->parent_sess);
+	
+	if (got_res)
+		hw_res_clean_resource_list(&hw_resources);
+	
+	if (ctl != NULL)
+		ddf_fun_destroy(ctl);
+	
+	return rc;
+}
+
+static void pciintel_init(void)
+{
+	ddf_log_init(NAME, LVL_ERROR);
+	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
+	pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
+}
+
+pci_fun_t *pci_fun_new(pci_bus_t *bus)
+{
+	pci_fun_t *fun;
+	
+	fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
+	if (fun == NULL)
+		return NULL;
+
+	fun->busptr = bus;
+	return fun;
+}
+
+void pci_fun_init(pci_fun_t *fun, int bus, int dev, int fn)
+{
+	fun->bus = bus;
+	fun->dev = dev;
+	fun->fn = fn;
+}
+
+void pci_fun_delete(pci_fun_t *fun)
+{
+	assert(fun != NULL);
+	hw_res_clean_resource_list(&fun->hw_resources);
+	free(fun);
+}
+
+char *pci_fun_create_name(pci_fun_t *fun)
+{
+	char *name = NULL;
+	
+	asprintf(&name, "%02x:%02x.%01x", fun->bus, fun->dev,
+	    fun->fn);
+	return name;
+}
+
+bool pci_alloc_resource_list(pci_fun_t *fun)
+{
+	fun->hw_resources.resources =
+	    (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
+	return fun->hw_resources.resources != NULL;
+}
+
+void pci_clean_resource_list(pci_fun_t *fun)
+{
+	if (fun->hw_resources.resources != NULL) {
+		free(fun->hw_resources.resources);
+		fun->hw_resources.resources = NULL;
+	}
+}
+
+/** Read the base address registers (BARs) of the function and add the addresses
+ * to its HW resource list.
+ *
+ * @param fun	PCI function
+ */
+void pci_read_bars(pci_fun_t *fun)
+{
+	/*
+	 * Position of the BAR in the PCI configuration address space of the
+	 * device.
+	 */
+	int addr = PCI_BASE_ADDR_0;
+	
+	while (addr <= PCI_BASE_ADDR_5)
+		addr = pci_read_bar(fun, addr);
+}
+
+size_t pci_bar_mask_to_size(uint32_t mask)
+{
+	size_t size = mask & ~(mask - 1);
+	return size;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS PCI bus driver (Intel method 1).\n");
+	pciintel_init();
+	return ddf_driver_main(&pci_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/pci/pciintel/pci.h
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/pci/pciintel/pci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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 pciintel
+ * @{
+ */
+/** @file
+ */
+
+#ifndef PCI_H_
+#define PCI_H_
+
+#include <ddf/driver.h>
+#include "pci_regs.h"
+
+#define PCI_MAX_HW_RES 8
+
+typedef struct pciintel_bus {
+	/** DDF device node */
+	ddf_dev_t *dnode;
+	uint32_t conf_io_addr;
+	void *conf_data_port;
+	void *conf_addr_port;
+	fibril_mutex_t conf_mutex;
+} pci_bus_t;
+
+typedef struct pci_fun_data {
+	pci_bus_t *busptr;
+	ddf_fun_t *fnode;
+
+	int bus;
+	int dev;
+	int fn;
+	int vendor_id;
+	int device_id;
+	hw_resource_list_t hw_resources;
+} pci_fun_t;
+
+extern void pci_fun_create_match_ids(pci_fun_t *);
+
+extern uint8_t pci_conf_read_8(pci_fun_t *, int);
+extern uint16_t pci_conf_read_16(pci_fun_t *, int);
+extern uint32_t pci_conf_read_32(pci_fun_t *, int);
+extern void pci_conf_write_8(pci_fun_t *, int, uint8_t);
+extern void pci_conf_write_16(pci_fun_t *, int, uint16_t);
+extern void pci_conf_write_32(pci_fun_t *, int, uint32_t);
+
+extern void pci_add_range(pci_fun_t *, uint64_t, size_t, bool);
+extern int pci_read_bar(pci_fun_t *, int);
+extern void pci_read_interrupt(pci_fun_t *);
+extern void pci_add_interrupt(pci_fun_t *, int);
+
+extern pci_fun_t *pci_fun_new(pci_bus_t *);
+extern void pci_fun_init(pci_fun_t *, int, int, int);
+extern void pci_fun_delete(pci_fun_t *);
+extern char *pci_fun_create_name(pci_fun_t *);
+
+extern void pci_bus_scan(pci_bus_t *, int);
+
+extern bool pci_alloc_resource_list(pci_fun_t *);
+extern void pci_clean_resource_list(pci_fun_t *);
+
+extern void pci_read_bars(pci_fun_t *);
+extern size_t pci_bar_mask_to_size(uint32_t);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/pci/pciintel/pci_regs.h
===================================================================
--- uspace/drv/bus/pci/pciintel/pci_regs.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/pci/pciintel/pci_regs.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 pciintel
+ * @{
+ */
+/** @file
+ */
+
+#ifndef PCI_REGS_H_
+#define PCI_REGS_H_
+
+/* Header types */
+#define PCI_HEADER_TYPE_DEV	0
+#define PCI_HEADER_TYPE_BRIDGE	1
+#define PCI_HEADER_TYPE_CARDBUS	2
+
+/* Header type 0 and 1 */
+#define PCI_VENDOR_ID		0x00
+#define PCI_DEVICE_ID		0x02
+#define PCI_COMMAND		0x04
+#define PCI_STATUS		0x06
+#define PCI_REVISION_ID		0x08
+#define PCI_PROG_IF		0x09
+#define PCI_SUB_CLASS		0x0A
+#define PCI_BASE_CLASS		0x0B
+#define PCI_CACHE_LINE_SIZE	0x0C
+#define PCI_LATENCY_TIMER	0x0D
+#define PCI_HEADER_TYPE		0x0E
+#define PCI_BIST		0x0F
+
+#define PCI_BASE_ADDR_0		0x10
+#define PCI_BASE_ADDR_1		0x14
+
+/* Header type 0 */
+#define PCI_BASE_ADDR_2			0x18
+#define PCI_BASE_ADDR_3			0x1B
+#define PCI_BASE_ADDR_4			0x20
+#define PCI_BASE_ADDR_5			0x24
+
+#define PCI_CARDBUS_CIS_PTR		0x28
+#define PCI_SUBSYSTEM_VENDOR_ID		0x2C
+#define PCI_SUBSYSTEM_ID		0x2E
+#define PCI_EXP_ROM_BASE		0x30
+#define PCI_CAP_PTR			0x34
+#define PCI_INT_LINE			0x3C
+#define PCI_INT_PIN			0x3D
+#define PCI_MIN_GNT			0x3E
+#define PCI_MAX_LAT			0x3F
+
+/* Header type 1 */
+#define PCI_BRIDGE_PRIM_BUS_NUM		0x18
+#define PCI_BRIDGE_SEC_BUS_NUM		0x19
+#define PCI_BRIDGE_SUBORD_BUS_NUM	0x1A
+#define PCI_BRIDGE_SEC_LATENCY_TIMER	0x1B
+#define PCI_BRIDGE_IO_BASE		0x1C
+#define PCI_BRIDGE_IO_LIMIT		0x1D
+#define PCI_BRIDGE_SEC_STATUS		0x1E
+#define PCI_BRIDGE_MEMORY_BASE		0x20
+#define PCI_BRIDGE_MEMORY_LIMIT		0x22
+#define PCI_BRIDGE_PREF_MEMORY_BASE	0x24
+#define PCI_BRIDGE_PREF_MEMORY_LIMIT	0x26
+#define PCI_BRIDGE_PREF_MEMORY_BASE_UP	0x28
+#define PCI_BRIDGE_PREF_MEMORY_LIMIT_UP	0x2C
+#define PCI_BRIDGE_IO_BASE_UP		0x30
+#define PCI_BRIDGE_IO_LIMIT_UP		0x32
+#define PCI_BRIDGE_EXP_ROM_BASE		0x38
+#define PCI_BRIDGE_INT_LINE		0x3C
+#define PCI_BRIDGE_INT_PIN		0x3D
+#define PCI_BRIDGE_CTL			0x3E
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/pci/pciintel/pciintel.ma
===================================================================
--- uspace/drv/bus/pci/pciintel/pciintel.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/pci/pciintel/pciintel.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 intel_pci
Index: uspace/drv/bus/usb/ehci/Makefile
===================================================================
--- uspace/drv/bus/usb/ehci/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ehci/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,48 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = ehci
+
+SOURCES = \
+	hc_iface.c \
+	main.c \
+	pci.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/ehci/ehci.h
===================================================================
--- uspace/drv/bus/usb/ehci/ehci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ehci/ehci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,48 @@
+/*
+ * 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 drvusbehci
+ * @{
+ */
+/** @file
+ * Common EHCI definitions.
+ */
+#ifndef DRV_EHCI_EHCI_H
+#define DRV_EHCI_EHCI_H
+
+#include <usbhc_iface.h>
+
+#define NAME "ehci"
+
+extern usbhc_iface_t ehci_hc_iface;
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ehci/ehci.ma
===================================================================
--- uspace/drv/bus/usb/ehci/ehci.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ehci/ehci.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,39 @@
+10 pci/ven=1002&dev=4345
+10 pci/ven=1002&dev=4386
+10 pci/ven=1002&dev=4396
+10 pci/ven=1002&dev=4373
+10 pci/ven=1022&dev=7463
+10 pci/ven=1022&dev=7808
+10 pci/ven=102f&dev=01b5
+10 pci/ven=10cf&dev=1415
+10 pci/ven=10de&dev=00e8
+10 pci/ven=10de&dev=055f
+10 pci/ven=10de&dev=056a
+10 pci/ven=10de&dev=077c
+10 pci/ven=10de&dev=077e
+10 pci/ven=10de&dev=0aa6
+10 pci/ven=10de&dev=0aa9
+10 pci/ven=10de&dev=0aaa
+10 pci/ven=10de&dev=0d9d
+10 pci/ven=1166&dev=0414
+10 pci/ven=1166&dev=0416
+10 pci/ven=1414&dev=5805
+10 pci/ven=1414&dev=5807
+10 pci/ven=15ad&dev=0770
+10 pci/ven=17a0&dev=8084
+10 pci/ven=8086&dev=24cd
+10 pci/ven=8086&dev=24dd
+10 pci/ven=8086&dev=265c
+10 pci/ven=8086&dev=268c
+10 pci/ven=8086&dev=27cc
+10 pci/ven=8086&dev=2836
+10 pci/ven=8086&dev=283a
+10 pci/ven=8086&dev=293a
+10 pci/ven=8086&dev=293c
+10 pci/ven=8086&dev=3a3a
+10 pci/ven=8086&dev=3a3c
+10 pci/ven=8086&dev=3a6a
+10 pci/ven=8086&dev=3a6c
+10 pci/ven=8086&dev=8117
+10 pci/ven=8086&dev=8807
+10 pci/ven=8086&dev=880f
Index: uspace/drv/bus/usb/ehci/hc_iface.c
===================================================================
--- uspace/drv/bus/usb/ehci/hc_iface.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ehci/hc_iface.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,327 @@
+/*
+ * 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 drvusbehci
+ * @{
+ */
+/** @file
+ * USB-HC interface implementation.
+ */
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
+#include <device/hw_res.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "ehci.h"
+
+#define UNSUPPORTED(methodname) \
+	usb_log_debug("Client called unsupported interface method " \
+	    "`%s()' in %s:%d.\n", \
+	    methodname, __FILE__, __LINE__)
+
+/** Found free USB address.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] speed Speed of the device that will get this address.
+ * @param[out] address Non-null pointer where to store the free address.
+ * @return Error code.
+ */
+static int request_address(ddf_fun_t *fun, usb_speed_t speed,
+    usb_address_t *address)
+{
+	UNSUPPORTED("request_address");
+
+	return ENOTSUP;
+}
+
+/** Bind USB address with device devman handle.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] handle Devman handle of the device.
+ * @return Error code.
+ */
+static int bind_address(ddf_fun_t *fun,
+    usb_address_t address, devman_handle_t handle)
+{
+	UNSUPPORTED("bind_address");
+
+	return ENOTSUP;
+}
+
+/** Find device handle by USB address.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	UNSUPPORTED("find_by_address");
+
+	return ENOTSUP;
+}
+
+/** Release previously requested address.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	UNSUPPORTED("release_address");
+
+	return ENOTSUP;
+}
+
+/** Register endpoint for bandwidth reservation.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] speed Endpoint speed (invalid means to use device one).
+ * @param[in] endpoint Endpoint number.
+ * @param[in] transfer_type USB transfer type.
+ * @param[in] direction Endpoint data direction.
+ * @param[in] max_packet_size Max packet size of the endpoint.
+ * @param[in] interval Polling interval.
+ * @return Error code.
+ */
+static int register_endpoint(ddf_fun_t *fun,
+    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	UNSUPPORTED("register_endpoint");
+
+	return ENOTSUP;
+}
+
+/** Unregister endpoint (free some bandwidth reservation).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint Endpoint number.
+ * @param[in] direction Endpoint data direction.
+ * @return Error code.
+ */
+static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	UNSUPPORTED("unregister_endpoint");
+
+	return ENOTSUP;
+}
+
+/** Schedule interrupt out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	UNSUPPORTED("interrupt_out");
+
+	return ENOTSUP;
+}
+
+/** Schedule interrupt in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	UNSUPPORTED("interrupt_in");
+
+	return ENOTSUP;
+}
+
+/** Schedule bulk out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_out(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	UNSUPPORTED("bulk_out");
+
+	return ENOTSUP;
+}
+
+/** Schedule bulk in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_in(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	UNSUPPORTED("bulk_in");
+
+	return ENOTSUP;
+}
+
+/** Schedule control write transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Data buffer (in USB endianess, allocated and
+ *	deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_write(ddf_fun_t *fun, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data_buffer, size_t data_buffer_size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	UNSUPPORTED("control_write");
+
+	return ENOTSUP;
+}
+
+/** Schedule control read transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_read(ddf_fun_t *fun, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data_buffer, size_t data_buffer_size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	UNSUPPORTED("control_read");
+
+	return ENOTSUP;
+}
+
+/** Host controller interface implementation for EHCI. */
+usbhc_iface_t ehci_hc_iface = {
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.find_by_address = find_by_address,
+	.release_address = release_address,
+
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.bulk_out = bulk_out,
+	.bulk_in = bulk_in,
+
+	.control_write = control_write,
+	.control_read = control_read
+};
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ehci/main.c
===================================================================
--- uspace/drv/bus/usb/ehci/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ehci/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 drvusbehci
+ * @{
+ */
+/** @file
+ * Main routines of EHCI driver.
+ */
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
+#include <device/hw_res.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "pci.h"
+#include "ehci.h"
+
+static int ehci_add_device(ddf_dev_t *device);
+/*----------------------------------------------------------------------------*/
+static driver_ops_t ehci_driver_ops = {
+	.add_device = ehci_add_device,
+};
+/*----------------------------------------------------------------------------*/
+static driver_t ehci_driver = {
+	.name = NAME,
+	.driver_ops = &ehci_driver_ops
+};
+static ddf_dev_ops_t hc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &ehci_hc_iface,
+};
+
+/*----------------------------------------------------------------------------*/
+/** Initializes a new ddf driver instance of EHCI hcd.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int ehci_add_device(ddf_dev_t *device)
+{
+	assert(device);
+#define CHECK_RET_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	return ret; \
+}
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
+	int irq = 0;
+
+	int ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_RETURN(ret,
+	    "Failed to get memory addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_info("Memory mapped regs at 0x%" PRIxn " (size %zu), IRQ %d.\n",
+	    reg_base, reg_size, irq);
+
+	ret = pci_disable_legacy(device, reg_base, reg_size, irq);
+	CHECK_RET_RETURN(ret,
+	    "Failed to disable legacy USB: %s.\n", str_error(ret));
+
+	ddf_fun_t *hc_fun = ddf_fun_create(device, fun_exposed, "ehci_hc");
+	if (hc_fun == NULL) {
+		usb_log_error("Failed to create EHCI function.\n");
+		return ENOMEM;
+	}
+	hc_fun->ops = &hc_ops;
+
+	ret = ddf_fun_bind(hc_fun);
+	CHECK_RET_RETURN(ret,
+	    "Failed to bind EHCI function: %s.\n",
+	    str_error(ret));
+	ret = ddf_fun_add_to_class(hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_RETURN(ret,
+	    "Failed to add EHCI to HC class: %s.\n",
+	    str_error(ret));
+
+	usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",
+	    device->name, device->handle);
+
+	return EOK;
+#undef CHECK_RET_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initializes global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	return ddf_driver_main(&ehci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ehci/pci.c
===================================================================
--- uspace/drv/bus/usb/ehci/pci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ehci/pci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,391 @@
+/*
+ * 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 drvusbehci
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the EHCI driver.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+#include <as.h>
+#include <devman.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <device/hw_res.h>
+
+#include <usb/debug.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+#define PAGE_SIZE_MASK 0xfffff000
+
+#define HCC_PARAMS_OFFSET 0x8
+#define HCC_PARAMS_EECP_MASK 0xff
+#define HCC_PARAMS_EECP_OFFSET 8
+
+#define CMD_OFFSET 0x0
+#define STS_OFFSET 0x4
+#define INT_OFFSET 0x8
+#define CFG_OFFSET 0x40
+
+#define USBCMD_RUN 1
+#define USBSTS_HALTED (1 << 12)
+
+#define USBLEGSUP_OFFSET 0
+#define USBLEGSUP_BIOS_CONTROL (1 << 16)
+#define USBLEGSUP_OS_CONTROL (1 << 24)
+#define USBLEGCTLSTS_OFFSET 4
+
+#define DEFAULT_WAIT 1000
+#define WAIT_STEP 10
+
+#define PCI_READ(size) \
+do { \
+	async_sess_t *parent_sess = \
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, \
+	    IPC_FLAG_BLOCKING); \
+	if (!parent_sess) \
+		return ENOMEM; \
+	\
+	sysarg_t add = (sysarg_t) address; \
+	sysarg_t val; \
+	\
+	async_exch_t *exch = async_exchange_begin(parent_sess); \
+	\
+	const int ret = \
+	    async_req_2_1(exch, DEV_IFACE_ID(PCI_DEV_IFACE), \
+	        IPC_M_CONFIG_SPACE_READ_##size, add, &val); \
+	\
+	async_exchange_end(exch); \
+	async_hangup(parent_sess); \
+	\
+	assert(value); \
+	\
+	*value = val; \
+	return ret; \
+} while (0)
+
+static int pci_read32(const ddf_dev_t *dev, int address, uint32_t *value)
+{
+	PCI_READ(32);
+}
+
+static int pci_read16(const ddf_dev_t *dev, int address, uint16_t *value)
+{
+	PCI_READ(16);
+}
+
+static int pci_read8(const ddf_dev_t *dev, int address, uint8_t *value)
+{
+	PCI_READ(8);
+}
+
+#define PCI_WRITE(size) \
+do { \
+	async_sess_t *parent_sess = \
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, \
+	    IPC_FLAG_BLOCKING); \
+	if (!parent_sess) \
+		return ENOMEM; \
+	\
+	sysarg_t add = (sysarg_t) address; \
+	sysarg_t val = value; \
+	\
+	async_exch_t *exch = async_exchange_begin(parent_sess); \
+	\
+	const int ret = \
+	    async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE), \
+	        IPC_M_CONFIG_SPACE_WRITE_##size, add, val); \
+	\
+	async_exchange_end(exch); \
+	async_hangup(parent_sess); \
+	\
+	return ret; \
+} while(0)
+
+static int pci_write32(const ddf_dev_t *dev, int address, uint32_t value)
+{
+	PCI_WRITE(32);
+}
+
+static int pci_write16(const ddf_dev_t *dev, int address, uint16_t value)
+{
+	PCI_WRITE(16);
+}
+
+static int pci_write8(const ddf_dev_t *dev, int address, uint8_t value)
+{
+	PCI_WRITE(8);
+}
+
+/** Get address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] mem_reg_address Base address of the memory range.
+ * @param[out] mem_reg_size Size of the memory range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(const ddf_dev_t *dev,
+    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
+{
+	assert(dev != NULL);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	hw_resource_list_t hw_resources;
+	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (rc != EOK) {
+		async_hangup(parent_sess);
+		return rc;
+	}
+	
+	uintptr_t mem_address = 0;
+	size_t mem_size = 0;
+	bool mem_found = false;
+	
+	int irq = 0;
+	bool irq_found = false;
+	
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			irq = res->res.interrupt.irq;
+			irq_found = true;
+			usb_log_debug2("Found interrupt: %d.\n", irq);
+			break;
+		case MEM_RANGE:
+			if (res->res.mem_range.address != 0
+			    && res->res.mem_range.size != 0 ) {
+				mem_address = res->res.mem_range.address;
+				mem_size = res->res.mem_range.size;
+				usb_log_debug2("Found mem: %" PRIxn" %zu.\n",
+				    mem_address, mem_size);
+				mem_found = true;
+			}
+		default:
+			break;
+		}
+	}
+	
+	if (mem_found && irq_found) {
+		*mem_reg_address = mem_address;
+		*mem_reg_size = mem_size;
+		*irq_no = irq;
+		rc = EOK;
+	} else {
+		rc = ENOENT;
+	}
+	
+	async_hangup(parent_sess);
+	return rc;
+}
+/*----------------------------------------------------------------------------*/
+/** Calls the PCI driver with a request to enable interrupts
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_enable_interrupts(const ddf_dev_t *device)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	const bool enabled = hw_res_enable_interrupt(parent_sess);
+	async_hangup(parent_sess);
+	
+	return enabled ? EOK : EIO;
+}
+/*----------------------------------------------------------------------------*/
+/** Implements BIOS handoff routine as decribed in EHCI spec
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_disable_legacy(
+    const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size, int irq)
+{
+	assert(device);
+	(void) pci_read16;
+	(void) pci_read8;
+	(void) pci_write16;
+
+#define CHECK_RET_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		return ret; \
+	} else (void)0
+
+	/* Map EHCI registers */
+	void *regs = NULL;
+	int ret = pio_enable((void*)reg_base, reg_size, &regs);
+	CHECK_RET_RETURN(ret, "Failed to map registers %p: %s.\n",
+	    (void *) reg_base, str_error(ret));
+
+	const uint32_t hcc_params =
+	    *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
+	usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
+
+	/* Read value of EHCI Extended Capabilities Pointer
+	 * position of EEC registers (points to PCI config space) */
+	const uint32_t eecp =
+	    (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
+	usb_log_debug("Value of EECP: %x.\n", eecp);
+
+	/* Read the first EEC. i.e. Legacy Support register */
+	uint32_t usblegsup;
+	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
+	CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
+	usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
+
+	/* Request control from firmware/BIOS, by writing 1 to highest byte.
+	 * (OS Control semaphore)*/
+	usb_log_debug("Requesting OS control.\n");
+	ret = pci_write8(device, eecp + USBLEGSUP_OFFSET + 3, 1);
+	CHECK_RET_RETURN(ret, "Failed to request OS EHCI control: %s.\n",
+	    str_error(ret));
+
+	size_t wait = 0;
+	/* Wait for BIOS to release control. */
+	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
+	while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
+		async_usleep(WAIT_STEP);
+		ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
+		wait += WAIT_STEP;
+	}
+
+
+	if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
+		usb_log_info("BIOS released control after %zu usec.\n", wait);
+	} else {
+		/* BIOS failed to hand over control, this should not happen. */
+		usb_log_warning( "BIOS failed to release control after "
+		    "%zu usecs, force it.\n", wait);
+		ret = pci_write32(device, eecp + USBLEGSUP_OFFSET,
+		    USBLEGSUP_OS_CONTROL);
+		CHECK_RET_RETURN(ret, "Failed to force OS control: %s.\n",
+		    str_error(ret));
+		/* Check capability type here, A value of 01h
+		 * identifies the capability as Legacy Support.
+		 * This extended capability requires one
+		 * additional 32-bit register for control/status information,
+		 * and this register is located at offset EECP+04h
+		 * */
+		if ((usblegsup & 0xff) == 1) {
+			/* Read the second EEC
+			 * Legacy Support and Control register */
+			uint32_t usblegctlsts;
+			ret = pci_read32(
+			    device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
+			CHECK_RET_RETURN(ret,
+			    "Failed to get USBLEGCTLSTS: %s.\n", str_error(ret));
+			usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n",
+			    usblegctlsts);
+			/* Zero SMI enables in legacy control register.
+			 * It should prevent pre-OS code from interfering. */
+			ret = pci_write32(device, eecp + USBLEGCTLSTS_OFFSET,
+			    0xe0000000); /* three upper bits are WC */
+			CHECK_RET_RETURN(ret,
+			    "Failed(%d) zero USBLEGCTLSTS.\n", ret);
+			udelay(10);
+			ret = pci_read32(
+			    device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
+			CHECK_RET_RETURN(ret,
+			    "Failed to get USBLEGCTLSTS 2: %s.\n",
+			    str_error(ret));
+			usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
+			    usblegctlsts);
+		}
+	}
+
+
+	/* Read again Legacy Support register */
+	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
+	CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
+	usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
+
+	/*
+	 * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT
+	 */
+
+	/* Get size of capability registers in memory space. */
+	const unsigned operation_offset = *(uint8_t*)regs;
+	usb_log_debug("USBCMD offset: %d.\n", operation_offset);
+
+	/* Zero USBCMD register. */
+	volatile uint32_t *usbcmd =
+	    (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET);
+	volatile uint32_t *usbsts =
+	    (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET);
+	volatile uint32_t *usbconf =
+	    (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET);
+	volatile uint32_t *usbint =
+	    (uint32_t*)((uint8_t*)regs + operation_offset + INT_OFFSET);
+	usb_log_debug("USBCMD value: %x.\n", *usbcmd);
+	if (*usbcmd & USBCMD_RUN) {
+		*usbsts = 0x3f; /* ack all interrupts */
+		*usbint = 0; /* disable all interrutps */
+		*usbconf = 0; /* relase control of RH ports */
+
+		*usbcmd = 0;
+		/* Wait until hc is halted */
+		while ((*usbsts & USBSTS_HALTED) == 0);
+		usb_log_info("EHCI turned off.\n");
+	} else {
+		usb_log_info("EHCI was not running.\n");
+	}
+	usb_log_debug("Registers: \n"
+	    "\t USBCMD: %x(0x00080000 = at least 1ms between interrupts)\n"
+	    "\t USBSTS: %x(0x00001000 = HC halted)\n"
+	    "\t USBINT: %x(0x0 = no interrupts).\n"
+	    "\t CONFIG: %x(0x0 = ports controlled by companion hc).\n",
+	    *usbcmd, *usbsts, *usbint, *usbconf);
+
+	return ret;
+#undef CHECK_RET_RETURN
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ehci/pci.h
===================================================================
--- uspace/drv/bus/usb/ehci/pci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ehci/pci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,48 @@
+/*
+ * 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 drvusbehci
+ * @{
+ */
+/** @file
+ * PCI related functions needed by EHCI driver.
+ */
+#ifndef DRV_EHCI_PCI_H
+#define DRV_EHCI_PCI_H
+
+#include <ddf/driver.h>
+
+int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(const ddf_dev_t *);
+int pci_disable_legacy(const ddf_dev_t *, uintptr_t, size_t, int);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/Makefile
===================================================================
--- uspace/drv/bus/usb/ohci/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = ohci
+
+SOURCES = \
+	batch.c \
+	endpoint_list.c \
+	hc.c \
+	hcd_endpoint.c \
+	iface.c \
+	main.c \
+	ohci.c \
+	pci.c \
+	root_hub.c \
+	hw_struct/endpoint_descriptor.c \
+	hw_struct/transfer_descriptor.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/ohci/batch.c
===================================================================
--- uspace/drv/bus/usb/ohci/batch.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/batch.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver USB transaction structure
+ */
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/usb.h>
+#include <usb/debug.h>
+
+#include "batch.h"
+#include "hcd_endpoint.h"
+#include "utils/malloc32.h"
+#include "hw_struct/endpoint_descriptor.h"
+#include "hw_struct/transfer_descriptor.h"
+
+/** OHCI specific data required for USB transfer */
+typedef struct ohci_transfer_batch {
+	/** Endpoint descriptor of the target endpoint. */
+	ed_t *ed;
+	/** List of TDs needed for the transfer */
+	td_t **tds;
+	/** Number of TDs used by the transfer */
+	size_t td_count;
+	/** Dummy TD to be left at the ED and used by the next transfer */
+	size_t leave_td;
+	/** Data buffer, must be accessible byb the OHCI hw. */
+	void *device_buffer;
+} ohci_transfer_batch_t;
+/*----------------------------------------------------------------------------*/
+static void batch_control(usb_transfer_batch_t *instance,
+    usb_direction_t data_dir, usb_direction_t status_dir);
+static void batch_data(usb_transfer_batch_t *instance);
+/*----------------------------------------------------------------------------*/
+/** Safely destructs ohci_transfer_batch_t structure
+ *
+ * @param[in] ohci_batch Instance to destroy.
+ */
+static void ohci_transfer_batch_dispose(void *ohci_batch)
+{
+	ohci_transfer_batch_t *instance = ohci_batch;
+	if (!instance)
+		return;
+	free32(instance->device_buffer);
+	unsigned i = 0;
+	if (instance->tds) {
+		for (; i< instance->td_count; ++i) {
+			if (i != instance->leave_td)
+				free32(instance->tds[i]);
+		}
+		free(instance->tds);
+	}
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Allocate memory initialize internal structures
+ *
+ * @param[in] fun DDF function to pass to callback.
+ * @param[in] ep Communication target
+ * @param[in] buffer Data source/destination.
+ * @param[in] buffer_size Size of the buffer.
+ * @param[in] setup_buffer Setup data source (if not NULL)
+ * @param[in] setup_size Size of setup_buffer (should be always 8)
+ * @param[in] func_in function to call on inbound transfer completion
+ * @param[in] func_out function to call on outbound transfer completion
+ * @param[in] arg additional parameter to func_in or func_out
+ * @return Valid pointer if all structures were successfully created,
+ * NULL otherwise.
+ *
+ * Allocates and initializes structures needed by the OHCI hw for the transfer.
+ */
+usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
+    char *buffer, size_t buffer_size,
+    const 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)
+{
+#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
+        if (ptr == NULL) { \
+                usb_log_error(message); \
+                if (instance) { \
+                        usb_transfer_batch_dispose(instance); \
+                } \
+                return NULL; \
+        } else (void)0
+
+	usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
+	CHECK_NULL_DISPOSE_RETURN(instance,
+	    "Failed to allocate batch instance.\n");
+	usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size,
+	    NULL, setup_size, func_in, func_out, arg, fun, NULL,
+	    ohci_transfer_batch_dispose);
+
+	const hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
+	assert(hcd_ep);
+
+	ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1);
+	CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
+	instance->private_data = data;
+
+	data->td_count =
+	    ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
+	/* Control transfer need Setup and Status stage */
+	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
+		data->td_count += 2;
+	}
+
+	/* We need an extra place for TD that is currently assigned to hcd_ep*/
+	data->tds = calloc(sizeof(td_t*), data->td_count + 1);
+	CHECK_NULL_DISPOSE_RETURN(data->tds,
+	    "Failed to allocate transfer descriptors.\n");
+
+	/* Add TD left over by the previous transfer */
+	data->tds[0] = hcd_ep->td;
+	data->leave_td = 0;
+	unsigned i = 1;
+	for (; i <= data->td_count; ++i) {
+		data->tds[i] = malloc32(sizeof(td_t));
+		CHECK_NULL_DISPOSE_RETURN(data->tds[i],
+		    "Failed to allocate TD %d.\n", i );
+	}
+
+	data->ed = hcd_ep->ed;
+
+	/* NOTE: OHCI is capable of handling buffer that crosses page boundaries
+	 * it is, however, not capable of handling buffer that occupies more
+	 * than two pages (the first page is computed using start pointer, the
+	 * other using the end pointer) */
+        if (setup_size + buffer_size > 0) {
+		data->device_buffer = malloc32(setup_size + buffer_size);
+                CHECK_NULL_DISPOSE_RETURN(data->device_buffer,
+                    "Failed to allocate device accessible buffer.\n");
+		instance->setup_buffer = data->device_buffer;
+		instance->data_buffer = data->device_buffer + setup_size;
+                memcpy(instance->setup_buffer, setup_buffer, setup_size);
+        }
+
+	return instance;
+}
+/*----------------------------------------------------------------------------*/
+/** Check batch TDs' status.
+ *
+ * @param[in] instance Batch structure to use.
+ * @return False, if there is an active TD, true otherwise.
+ *
+ * Walk all TDs (usually there is just one). Stop with false if there is an
+ * active TD. Stop with true if an error is found. Return true if the walk
+ * completes with the last TD.
+ */
+bool batch_is_complete(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n",
+	    instance, data->td_count);
+	usb_log_debug("ED: %x:%x:%x:%x.\n",
+	    data->ed->status, data->ed->td_head, data->ed->td_tail,
+	    data->ed->next);
+	size_t i = 0;
+	instance->transfered_size = instance->buffer_size;
+	for (; i < data->td_count; ++i) {
+		assert(data->tds[i] != NULL);
+		usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
+		    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
+		    data->tds[i]->be);
+		if (!td_is_finished(data->tds[i])) {
+			return false;
+		}
+		instance->error = td_error(data->tds[i]);
+		if (instance->error != EOK) {
+			usb_log_debug("Batch(%p) found error TD(%zu):%x.\n",
+			    instance, i, data->tds[i]->status);
+			/* Make sure TD queue is empty (one TD),
+			 * ED should be marked as halted */
+			data->ed->td_tail =
+			    (data->ed->td_head & ED_TDTAIL_PTR_MASK);
+			++i;
+			break;
+		}
+	}
+	data->leave_td = i;
+	assert(data->leave_td <= data->td_count);
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
+	assert(hcd_ep);
+	hcd_ep->td = data->tds[i];
+	assert(i > 0);
+	for (--i;i < data->td_count; ++i)
+		instance->transfered_size -= td_remain_size(data->tds[i]);
+
+	/* Clear possible ED HALT */
+	data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+	const uint32_t pa = addr_to_phys(hcd_ep->td);
+	assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
+	assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
+
+	return true;
+}
+/*----------------------------------------------------------------------------*/
+/** Starts execution of the TD list
+ *
+ * @param[in] instance Batch structure to use
+ */
+void batch_commit(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	ed_set_end_td(data->ed, data->tds[data->td_count]);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares control write transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control transfer using direction OUT(data stage) and
+ * IN(status stage).
+ */
+void batch_control_write(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
+	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares control read transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control transfer using direction IN(data stage) and
+ * OUT(status stage).
+ */
+void batch_control_read(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
+	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare interrupt in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
+void batch_interrupt_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_data(instance);
+	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare interrupt out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
+void batch_interrupt_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	batch_data(instance);
+	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare bulk in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
+void batch_bulk_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_data(instance);
+	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare bulk out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
+void batch_bulk_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	batch_data(instance);
+	usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare generic control transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] data_dir Direction to use for data stage.
+ * @param[in] status_dir Direction to use for status stage.
+ *
+ * Setup stage with toggle 0 and direction BOTH(SETUP_PID)
+ * Data stage with alternating toggle and direction supplied by parameter.
+ * Status stage with toggle 1 and direction supplied by parameter.
+ */
+void batch_control(usb_transfer_batch_t *instance,
+    usb_direction_t data_dir, usb_direction_t status_dir)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
+	    data->ed->status, data->ed->td_tail, data->ed->td_head,
+	    data->ed->next);
+	int toggle = 0;
+	/* setup stage */
+	td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
+		instance->setup_size, toggle);
+	td_set_next(data->tds[0], data->tds[1]);
+	usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
+	    data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
+
+	/* data stage */
+	size_t td_current = 1;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
+		    OHCI_TD_MAX_TRANSFER : remain_size;
+		toggle = 1 - toggle;
+
+		td_init(data->tds[td_current], data_dir, buffer,
+		    transfer_size, toggle);
+		td_set_next(data->tds[td_current], data->tds[td_current + 1]);
+		usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
+		    data->tds[td_current]->status, data->tds[td_current]->cbp,
+		    data->tds[td_current]->next, data->tds[td_current]->be);
+
+		buffer += transfer_size;
+		remain_size -= transfer_size;
+		assert(td_current < data->td_count - 1);
+		++td_current;
+	}
+
+	/* status stage */
+	assert(td_current == data->td_count - 1);
+	td_init(data->tds[td_current], status_dir, NULL, 0, 1);
+	td_set_next(data->tds[td_current], data->tds[td_current + 1]);
+	usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
+	    data->tds[td_current]->status, data->tds[td_current]->cbp,
+	    data->tds[td_current]->next, data->tds[td_current]->be);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare generic data transfer
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Direction is supplied by the associated ep and toggle is maintained by the
+ * OHCI hw in ED.
+ */
+void batch_data(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
+	    data->ed->status, data->ed->td_tail, data->ed->td_head,
+	    data->ed->next);
+
+	size_t td_current = 0;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		const size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER
+		    ? OHCI_TD_MAX_TRANSFER : remain_size;
+
+		td_init(data->tds[td_current], instance->ep->direction,
+		    buffer, transfer_size, -1);
+		td_set_next(data->tds[td_current], data->tds[td_current + 1]);
+		usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
+		    data->tds[td_current]->status, data->tds[td_current]->cbp,
+		    data->tds[td_current]->next, data->tds[td_current]->be);
+
+		buffer += transfer_size;
+		remain_size -= transfer_size;
+		assert(td_current < data->td_count);
+		++td_current;
+	}
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/batch.h
===================================================================
--- uspace/drv/bus/usb/ohci/batch.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/batch.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver USB transaction structure
+ */
+#ifndef DRV_OHCI_BATCH_H
+#define DRV_OHCI_BATCH_H
+
+#include <usbhc_iface.h>
+#include <usb/usb.h>
+#include <usb/host/device_keeper.h>
+#include <usb/host/endpoint.h>
+#include <usb/host/batch.h>
+
+usb_transfer_batch_t * batch_get(
+    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
+    const 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(usb_transfer_batch_t *instance);
+
+void batch_commit(usb_transfer_batch_t *instance);
+
+void batch_control_write(usb_transfer_batch_t *instance);
+
+void batch_control_read(usb_transfer_batch_t *instance);
+
+void batch_interrupt_in(usb_transfer_batch_t *instance);
+
+void batch_interrupt_out(usb_transfer_batch_t *instance);
+
+void batch_bulk_in(usb_transfer_batch_t *instance);
+
+void batch_bulk_out(usb_transfer_batch_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/endpoint_list.c
===================================================================
--- uspace/drv/bus/usb/ohci/endpoint_list.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/endpoint_list.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver transfer list implementation
+ */
+#include <errno.h>
+#include <usb/debug.h>
+#include <arch/barrier.h>
+
+#include "endpoint_list.h"
+
+/** Initialize transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ * @param[in] name Name of the new list.
+ * @return Error code
+ *
+ * Allocates memory for internal ed_t structure.
+ */
+int endpoint_list_init(endpoint_list_t *instance, const char *name)
+{
+	assert(instance);
+	instance->name = name;
+	instance->list_head = malloc32(sizeof(ed_t));
+	if (!instance->list_head) {
+		usb_log_error("Failed to allocate list head.\n");
+		return ENOMEM;
+	}
+	instance->list_head_pa = addr_to_phys(instance->list_head);
+	usb_log_debug2("Transfer list %s setup with ED: %p(0x%0" PRIx32 ")).\n",
+	    name, instance->list_head, instance->list_head_pa);
+
+	ed_init(instance->list_head, NULL);
+	list_initialize(&instance->endpoint_list);
+	fibril_mutex_initialize(&instance->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Set the next list in transfer list chain.
+ *
+ * @param[in] instance List to lead.
+ * @param[in] next List to append.
+ *
+ * Does not check whether this replaces an existing list.
+ */
+void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
+{
+	assert(instance);
+	assert(next);
+	ed_append_ed(instance->list_head, next->list_head);
+}
+/*----------------------------------------------------------------------------*/
+/** Add endpoint to the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] endpoint Endpoint to add.
+ *
+ * The endpoint is added to the end of the list and queue.
+ */
+void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
+{
+	assert(instance);
+	assert(hcd_ep);
+	usb_log_debug2("Queue %s: Adding endpoint(%p).\n",
+	    instance->name, hcd_ep);
+
+	fibril_mutex_lock(&instance->guard);
+
+	ed_t *last_ed = NULL;
+	/* Add to the hardware queue. */
+	if (list_empty(&instance->endpoint_list)) {
+		/* There are no active EDs */
+		last_ed = instance->list_head;
+	} else {
+		/* There are active EDs, get the last one */
+		hcd_endpoint_t *last = list_get_instance(
+		    list_last(&instance->endpoint_list), hcd_endpoint_t, link);
+		last_ed = last->ed;
+	}
+	/* Keep link */
+	hcd_ep->ed->next = last_ed->next;
+	/* Make sure ED is written to the memory */
+	write_barrier();
+
+	/* Add ed to the hw queue */
+	ed_append_ed(last_ed, hcd_ep->ed);
+	/* Make sure ED is updated */
+	write_barrier();
+
+	/* Add to the sw list */
+	list_append(&hcd_ep->link, &instance->endpoint_list);
+
+	hcd_endpoint_t *first = list_get_instance(
+	    list_first(&instance->endpoint_list), hcd_endpoint_t, link);
+	usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n",
+		hcd_ep, instance->name, first, first->ed);
+	if (last_ed == instance->list_head) {
+		usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n",
+		    instance->name, last_ed, instance->list_head_pa,
+		    last_ed->status, last_ed->td_tail, last_ed->td_head,
+		    last_ed->next);
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Remove endpoint from the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] endpoint Endpoint to remove.
+ */
+void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
+{
+	assert(instance);
+	assert(instance->list_head);
+	assert(hcd_ep);
+	assert(hcd_ep->ed);
+
+	fibril_mutex_lock(&instance->guard);
+
+	usb_log_debug2(
+	    "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
+
+	const char *qpos = NULL;
+	ed_t *prev_ed;
+	/* Remove from the hardware queue */
+	if (list_first(&instance->endpoint_list) == &hcd_ep->link) {
+		/* I'm the first one here */
+		prev_ed = instance->list_head;
+		qpos = "FIRST";
+	} else {
+		hcd_endpoint_t *prev =
+		    list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link);
+		prev_ed = prev->ed;
+		qpos = "NOT FIRST";
+	}
+	assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
+	prev_ed->next = hcd_ep->ed->next;
+	/* Make sure ED is updated */
+	write_barrier();
+
+	usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
+	    hcd_ep, qpos, instance->name, hcd_ep->ed->next);
+
+	/* Remove from the endpoint list */
+	list_remove(&hcd_ep->link);
+	fibril_mutex_unlock(&instance->guard);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/endpoint_list.h
===================================================================
--- uspace/drv/bus/usb/ohci/endpoint_list.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/endpoint_list.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver transfer list structure
+ */
+#ifndef DRV_OHCI_ENDPOINT_LIST_H
+#define DRV_OHCI_ENDPOINT_LIST_H
+
+#include <fibril_synch.h>
+
+#include "hcd_endpoint.h"
+#include "hw_struct/endpoint_descriptor.h"
+#include "utils/malloc32.h"
+
+/** Structure maintains both OHCI queue and software list of active endpoints.*/
+typedef struct endpoint_list {
+	/** Guard against add/remove races */
+	fibril_mutex_t guard;
+	/** OHCI hw structure at the beginning of the queue */
+	ed_t *list_head;
+	/** Physical address of the first(dummy) ED */
+	uint32_t list_head_pa;
+	/** Assigned name, provides nicer debug output */
+	const char *name;
+	/** Sw list of all active EDs */
+	list_t endpoint_list;
+} endpoint_list_t;
+
+/** Dispose transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ *
+ * Frees memory of the internal ed_t structure.
+ */
+static inline void endpoint_list_fini(endpoint_list_t *instance)
+{
+	assert(instance);
+	free32(instance->list_head);
+}
+
+int endpoint_list_init(endpoint_list_t *instance, const char *name);
+void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
+void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
+void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,625 @@
+/*
+ * 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 drvusbohcihc
+ * @{
+ */
+/** @file
+ * @brief OHCI Host controller driver routines
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <adt/list.h>
+#include <libarch/ddi.h>
+
+#include <usb/debug.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+
+#include "hc.h"
+#include "hcd_endpoint.h"
+
+#define OHCI_USED_INTERRUPTS \
+    (I_SO | I_WDH | I_UE | I_RHSC)
+static int interrupt_emulator(hc_t *instance);
+static void hc_gain_control(hc_t *instance);
+static int hc_init_transfer_lists(hc_t *instance);
+static int hc_init_memory(hc_t *instance);
+/*----------------------------------------------------------------------------*/
+/** Announce OHCI root hub to the DDF
+ *
+ * @param[in] instance OHCI driver intance
+ * @param[in] hub_fun DDF fuction representing OHCI root hub
+ * @return Error code
+ */
+int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
+{
+	assert(instance);
+	assert(hub_fun);
+
+	const usb_address_t hub_address =
+	    device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
+	if (hub_address <= 0) {
+		usb_log_error("Failed to get OHCI root hub address: %s\n",
+		    str_error(hub_address));
+		return hub_address;
+	}
+	instance->rh.address = hub_address;
+	usb_device_keeper_bind(
+	    &instance->manager, hub_address, hub_fun->handle);
+
+#define CHECK_RET_RELEASE(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	hc_remove_endpoint(instance, hub_address, 0, USB_DIRECTION_BOTH); \
+	usb_device_keeper_release(&instance->manager, hub_address); \
+	return ret; \
+} else (void)0
+
+	int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
+	    USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
+	CHECK_RET_RELEASE(ret, "Failed(%d) to add OHCI rh endpoint 0.\n", ret);
+
+	char *match_str = NULL;
+	/* DDF needs heap allocated string */
+	ret = asprintf(&match_str, "usb&class=hub");
+	ret = ret > 0 ? 0 : ret;
+	CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret);
+
+	ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
+	CHECK_RET_RELEASE(ret, "Failed(%d) add root hub match-id.\n", ret);
+
+	ret = ddf_fun_bind(hub_fun);
+	CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret);
+
+	return EOK;
+#undef CHECK_RET_RELEASE
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize OHCI hc driver structure
+ *
+ * @param[in] instance Memory place for the structure.
+ * @param[in] regs Address of the memory mapped I/O registers.
+ * @param[in] reg_size Size of the memory mapped area.
+ * @param[in] interrupts True if w interrupts should be used
+ * @return Error code
+ */
+int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
+{
+	assert(instance);
+	int ret = EOK;
+#define CHECK_RET_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
+
+	ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers);
+	CHECK_RET_RETURN(ret,
+	    "Failed(%d) to gain access to device registers: %s.\n",
+	    ret, str_error(ret));
+
+	list_initialize(&instance->pending_batches);
+	usb_device_keeper_init(&instance->manager);
+	ret = usb_endpoint_manager_init(&instance->ep_manager,
+	    BANDWIDTH_AVAILABLE_USB11);
+	CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
+	    str_error(ret));
+
+	ret = hc_init_memory(instance);
+	CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",
+	    str_error(ret));
+#undef CHECK_RET_RETURN
+
+	fibril_mutex_initialize(&instance->guard);
+	hc_gain_control(instance);
+
+	rh_init(&instance->rh, instance->registers);
+
+	if (!interrupts) {
+		instance->interrupt_emulator =
+		    fibril_create((int(*)(void*))interrupt_emulator, instance);
+		fibril_add_ready(instance->interrupt_emulator);
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Create end register endpoint structures
+ *
+ * @param[in] instance OHCI driver structure.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint USB endpoint number.
+ * @param[in] speed Communication speeed of the device.
+ * @param[in] type Endpoint's transfer type.
+ * @param[in] direction Endpoint's direction.
+ * @param[in] mps Maximum packet size the endpoint accepts.
+ * @param[in] size Maximum allowed buffer size.
+ * @param[in] interval Time between transfers(interrupt transfers only).
+ * @return Error code
+ */
+int hc_add_endpoint(
+    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
+    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
+    size_t mps, size_t size, unsigned interval)
+{
+	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	if (ep == NULL)
+		return ENOMEM;
+	int ret =
+	    endpoint_init(ep, address, endpoint, direction, type, speed, mps);
+	if (ret != EOK) {
+		free(ep);
+		return ret;
+	}
+
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
+	if (hcd_ep == NULL) {
+		endpoint_destroy(ep);
+		return ENOMEM;
+	}
+
+	ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
+	if (ret != EOK) {
+		hcd_endpoint_clear(ep);
+		endpoint_destroy(ep);
+		return ret;
+	}
+
+	/* Enqueue hcd_ep */
+	switch (ep->transfer_type) {
+	case USB_TRANSFER_CONTROL:
+		instance->registers->control &= ~C_CLE;
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control_current = 0;
+		instance->registers->control |= C_CLE;
+		break;
+	case USB_TRANSFER_BULK:
+		instance->registers->control &= ~C_BLE;
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control |= C_BLE;
+		break;
+	case USB_TRANSFER_ISOCHRONOUS:
+	case USB_TRANSFER_INTERRUPT:
+		instance->registers->control &= (~C_PLE & ~C_IE);
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control |= C_PLE | C_IE;
+		break;
+	default:
+		break;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Dequeue and delete endpoint structures
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint USB endpoint number.
+ * @param[in] direction Direction of the endpoint.
+ * @return Error code
+ */
+int hc_remove_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
+	    address, endpoint, direction, NULL);
+	if (ep == NULL) {
+		usb_log_error("Endpoint unregister failed: No such EP.\n");
+		fibril_mutex_unlock(&instance->guard);
+		return ENOENT;
+	}
+
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
+	if (hcd_ep) {
+		/* Dequeue hcd_ep */
+		switch (ep->transfer_type) {
+		case USB_TRANSFER_CONTROL:
+			instance->registers->control &= ~C_CLE;
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control_current = 0;
+			instance->registers->control |= C_CLE;
+			break;
+		case USB_TRANSFER_BULK:
+			instance->registers->control &= ~C_BLE;
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control |= C_BLE;
+			break;
+		case USB_TRANSFER_ISOCHRONOUS:
+		case USB_TRANSFER_INTERRUPT:
+			instance->registers->control &= (~C_PLE & ~C_IE);
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control |= C_PLE | C_IE;
+			break;
+		default:
+			break;
+		}
+		hcd_endpoint_clear(ep);
+	} else {
+		usb_log_warning("Endpoint without hcd equivalent structure.\n");
+	}
+	int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
+	    address, endpoint, direction);
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Get access to endpoint structures
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint USB endpoint number.
+ * @param[in] direction Direction of the endpoint.
+ * @param[out] bw Reserved bandwidth.
+ * @return Error code
+ */
+endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
+	    address, endpoint, direction, bw);
+	fibril_mutex_unlock(&instance->guard);
+	return ep;
+}
+/*----------------------------------------------------------------------------*/
+/** Add USB transfer to the schedule.
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @param[in] batch Batch representing the transfer.
+ * @return Error code.
+ */
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	assert(batch->ep);
+
+	/* Check for root hub communication */
+	if (batch->ep->address == instance->rh.address) {
+		return rh_request(&instance->rh, batch);
+	}
+
+	fibril_mutex_lock(&instance->guard);
+	list_append(&batch->link, &instance->pending_batches);
+	batch_commit(batch);
+
+	/* Control and bulk schedules need a kick to start working */
+	switch (batch->ep->transfer_type)
+	{
+	case USB_TRANSFER_CONTROL:
+		instance->registers->command_status |= CS_CLF;
+		break;
+	case USB_TRANSFER_BULK:
+		instance->registers->command_status |= CS_BLF;
+		break;
+	default:
+		break;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Interrupt handling routine
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @param[in] status Value of the status register at the time of interrupt.
+ */
+void hc_interrupt(hc_t *instance, uint32_t status)
+{
+	assert(instance);
+	if ((status & ~I_SF) == 0) /* ignore sof status */
+		return;
+	usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
+	if (status & I_RHSC)
+		rh_interrupt(&instance->rh);
+
+	if (status & I_WDH) {
+		fibril_mutex_lock(&instance->guard);
+		usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
+		    instance->registers->hcca,
+		    (void *) addr_to_phys(instance->hcca));
+		usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
+		    instance->registers->periodic_current);
+
+		link_t *current = instance->pending_batches.head.next;
+		while (current != &instance->pending_batches.head) {
+			link_t *next = current->next;
+			usb_transfer_batch_t *batch =
+			    usb_transfer_batch_from_link(current);
+
+			if (batch_is_complete(batch)) {
+				list_remove(current);
+				usb_transfer_batch_finish(batch);
+			}
+
+			current = next;
+		}
+		fibril_mutex_unlock(&instance->guard);
+	}
+
+	if (status & I_UE) {
+		hc_start_hw(instance);
+	}
+
+}
+/*----------------------------------------------------------------------------*/
+/** Check status register regularly
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @return Error code
+ */
+int interrupt_emulator(hc_t *instance)
+{
+	assert(instance);
+	usb_log_info("Started interrupt emulator.\n");
+	while (1) {
+		const uint32_t status = instance->registers->interrupt_status;
+		instance->registers->interrupt_status = status;
+		hc_interrupt(instance, status);
+		async_usleep(10000);
+	}
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Turn off any (BIOS)driver that might be in control of the device.
+ *
+ * @param[in] instance OHCI hc driver structure.
+ */
+void hc_gain_control(hc_t *instance)
+{
+	assert(instance);
+	usb_log_debug("Requesting OHCI control.\n");
+	/* Turn off legacy emulation */
+	volatile uint32_t *ohci_emulation_reg =
+	    (uint32_t*)((char*)instance->registers + 0x100);
+	usb_log_debug("OHCI legacy register %p: %x.\n",
+	    ohci_emulation_reg, *ohci_emulation_reg);
+	/* Do not change A20 state */
+	*ohci_emulation_reg &= 0x100;
+	usb_log_debug("OHCI legacy register %p: %x.\n",
+	    ohci_emulation_reg, *ohci_emulation_reg);
+
+	/* Interrupt routing enabled => smm driver is active */
+	if (instance->registers->control & C_IR) {
+		usb_log_debug("SMM driver: request ownership change.\n");
+		instance->registers->command_status |= CS_OCR;
+		while (instance->registers->control & C_IR) {
+			async_usleep(1000);
+		}
+		usb_log_info("SMM driver: Ownership taken.\n");
+		instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);
+		async_usleep(50000);
+		return;
+	}
+
+	const unsigned hc_status =
+	    (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK;
+	/* Interrupt routing disabled && status != USB_RESET => BIOS active */
+	if (hc_status != C_HCFS_RESET) {
+		usb_log_debug("BIOS driver found.\n");
+		if (hc_status == C_HCFS_OPERATIONAL) {
+			usb_log_info("BIOS driver: HC operational.\n");
+			return;
+		}
+		/* HC is suspended assert resume for 20ms */
+		instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
+		async_usleep(20000);
+		usb_log_info("BIOS driver: HC resumed.\n");
+		return;
+	}
+
+	/* HC is in reset (hw startup) => no other driver
+	 * maintain reset for at least the time specified in USB spec (50 ms)*/
+	usb_log_debug("Host controller found in reset state.\n");
+	async_usleep(50000);
+}
+/*----------------------------------------------------------------------------*/
+/** OHCI hw initialization routine.
+ *
+ * @param[in] instance OHCI hc driver structure.
+ */
+void hc_start_hw(hc_t *instance)
+{
+	/* OHCI guide page 42 */
+	assert(instance);
+	usb_log_debug2("Started hc initialization routine.\n");
+
+	/* Save contents of fm_interval register */
+	const uint32_t fm_interval = instance->registers->fm_interval;
+	usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
+
+	/* Reset hc */
+	usb_log_debug2("HC reset.\n");
+	size_t time = 0;
+	instance->registers->command_status = CS_HCR;
+	while (instance->registers->command_status & CS_HCR) {
+		async_usleep(10);
+		time += 10;
+	}
+	usb_log_debug2("HC reset complete in %zu us.\n", time);
+
+	/* Restore fm_interval */
+	instance->registers->fm_interval = fm_interval;
+	assert((instance->registers->command_status & CS_HCR) == 0);
+
+	/* hc is now in suspend state */
+	usb_log_debug2("HC should be in suspend state(%x).\n",
+	    instance->registers->control);
+
+	/* Use HCCA */
+	instance->registers->hcca = addr_to_phys(instance->hcca);
+
+	/* Use queues */
+	instance->registers->bulk_head =
+	    instance->lists[USB_TRANSFER_BULK].list_head_pa;
+	usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
+	    instance->lists[USB_TRANSFER_BULK].list_head,
+	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
+
+	instance->registers->control_head =
+	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
+	usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
+	    instance->lists[USB_TRANSFER_CONTROL].list_head,
+	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
+
+	/* Enable queues */
+	instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
+	usb_log_debug2("All queues enabled(%x).\n",
+	    instance->registers->control);
+
+	/* Enable interrupts */
+	instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;
+	usb_log_debug2("Enabled interrupts: %x.\n",
+	    instance->registers->interrupt_enable);
+	instance->registers->interrupt_enable = I_MI;
+
+	/* Set periodic start to 90% */
+	uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
+	instance->registers->periodic_start = (frame_length / 10) * 9;
+	usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
+	    instance->registers->periodic_start,
+	    instance->registers->periodic_start, frame_length);
+
+	instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
+	usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
+	    instance->registers->control);
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize schedule queues
+ *
+ * @param[in] instance OHCI hc driver structure
+ * @return Error code
+ */
+int hc_init_transfer_lists(hc_t *instance)
+{
+	assert(instance);
+#define SETUP_ENDPOINT_LIST(type) \
+do { \
+	const char *name = usb_str_transfer_type(type); \
+	int ret = endpoint_list_init(&instance->lists[type], name); \
+	if (ret != EOK) { \
+		usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
+		    ret, name); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
+		return ret; \
+	} \
+} while (0)
+
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
+#undef SETUP_ENDPOINT_LIST
+	endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
+	    &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize memory structures used by the OHCI hcd.
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @return Error code.
+ */
+int hc_init_memory(hc_t *instance)
+{
+	assert(instance);
+
+	bzero(&instance->rh, sizeof(instance->rh));
+	/* Init queues */
+	const int ret = hc_init_transfer_lists(instance);
+	if (ret != EOK) {
+		return ret;
+	}
+
+	/*Init HCCA */
+	instance->hcca = malloc32(sizeof(hcca_t));
+	if (instance->hcca == NULL)
+		return ENOMEM;
+	bzero(instance->hcca, sizeof(hcca_t));
+	usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
+
+	unsigned i = 0;
+	for (; i < 32; ++i) {
+		instance->hcca->int_ep[i] =
+		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
+	}
+	usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
+	    instance->lists[USB_TRANSFER_INTERRUPT].list_head,
+	    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
+
+	/* Init interrupt code */
+	instance->interrupt_code.cmds = instance->interrupt_commands;
+	instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS;
+	{
+		/* Read status register */
+		instance->interrupt_commands[0].cmd = CMD_MEM_READ_32;
+		instance->interrupt_commands[0].dstarg = 1;
+		instance->interrupt_commands[0].addr =
+		    (void*)&instance->registers->interrupt_status;
+
+		/* Test whether we are the interrupt cause */
+		instance->interrupt_commands[1].cmd = CMD_BTEST;
+		instance->interrupt_commands[1].value =
+		    OHCI_USED_INTERRUPTS;
+		instance->interrupt_commands[1].srcarg = 1;
+		instance->interrupt_commands[1].dstarg = 2;
+
+		/* Predicate cleaning and accepting */
+		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
+		instance->interrupt_commands[2].value = 2;
+		instance->interrupt_commands[2].srcarg = 2;
+
+		/* Write-clean status register */
+		instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32;
+		instance->interrupt_commands[3].srcarg = 1;
+		instance->interrupt_commands[3].addr =
+		    (void*)&instance->registers->interrupt_status;
+
+		/* Accept interrupt */
+		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
+	}
+
+	return EOK;
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hc.h
===================================================================
--- uspace/drv/bus/usb/ohci/hc.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI host controller driver structure
+ */
+#ifndef DRV_OHCI_HC_H
+#define DRV_OHCI_HC_H
+
+#include <fibril.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <ddi.h>
+
+#include <usb/usb.h>
+#include <usb/host/device_keeper.h>
+#include <usb/host/usb_endpoint_manager.h>
+#include <usbhc_iface.h>
+
+#include "batch.h"
+#include "ohci_regs.h"
+#include "root_hub.h"
+#include "endpoint_list.h"
+#include "hw_struct/hcca.h"
+
+#define OHCI_NEEDED_IRQ_COMMANDS 5
+
+/** Main OHCI drier structure */
+typedef struct hc {
+	/** USB bus driver, devices and addresses */
+	usb_device_keeper_t manager;
+	/** USB bus driver, endpoints */
+	usb_endpoint_manager_t ep_manager;
+
+	/** Memory mapped I/O registers area */
+	ohci_regs_t *registers;
+	/** Host controller communication area structure */
+	hcca_t *hcca;
+
+	/** Transfer schedules */
+	endpoint_list_t lists[4];
+	/** List of active transfers */
+	list_t pending_batches;
+
+	/** Fibril for periodic checks if interrupts can't be used */
+	fid_t interrupt_emulator;
+
+	/** Guards schedule and endpoint manipulation */
+	fibril_mutex_t guard;
+
+	/** Code to be executed in kernel interrupt handler */
+	irq_code_t interrupt_code;
+
+	/** Commands that form interrupt code */
+	irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS];
+
+	/** USB hub emulation structure */
+	rh_t rh;
+} hc_t;
+
+int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
+int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
+void hc_start_hw(hc_t *instance);
+
+/** Safely dispose host controller internal structures
+ *
+ * @param[in] instance Host controller structure to use.
+ */
+static inline void hc_fini(hc_t *instance)
+	{ /* TODO: implement*/ };
+
+int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
+    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
+    size_t max_packet_size, size_t size, unsigned interval);
+int hc_remove_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction);
+endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
+
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
+void hc_interrupt(hc_t *instance, uint32_t status);
+
+/** Get and cast pointer to the driver data
+ *
+ * @param[in] fun DDF function pointer
+ * @return cast pointer to driver_data
+ */
+static inline hc_t * fun_to_hc(ddf_fun_t *fun)
+	{ return fun->driver_data; }
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hcd_endpoint.c
===================================================================
--- uspace/drv/bus/usb/ohci/hcd_endpoint.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hcd_endpoint.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include "utils/malloc32.h"
+#include "hcd_endpoint.h"
+
+/** Callback to set toggle on ED.
+ *
+ * @param[in] hcd_ep hcd endpoint structure
+ * @param[in] toggle new value of toggle bit
+ */
+static void hcd_ep_toggle_set(void *hcd_ep, int toggle)
+{
+	hcd_endpoint_t *instance = hcd_ep;
+	assert(instance);
+	assert(instance->ed);
+	ed_toggle_set(instance->ed, toggle);
+}
+/*----------------------------------------------------------------------------*/
+/** Callback to get value of toggle bit.
+ *
+ * @param[in] hcd_ep hcd endpoint structure
+ * @return Current value of toggle bit.
+ */
+static int hcd_ep_toggle_get(void *hcd_ep)
+{
+	hcd_endpoint_t *instance = hcd_ep;
+	assert(instance);
+	assert(instance->ed);
+	return ed_toggle_get(instance->ed);
+}
+/*----------------------------------------------------------------------------*/
+/** Creates new hcd endpoint representation.
+ *
+ * @param[in] ep USBD endpoint structure
+ * @return pointer to a new hcd endpoint structure, NULL on failure.
+ */
+hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep)
+{
+	assert(ep);
+	hcd_endpoint_t *hcd_ep = malloc(sizeof(hcd_endpoint_t));
+	if (hcd_ep == NULL)
+		return NULL;
+
+	hcd_ep->ed = malloc32(sizeof(ed_t));
+	if (hcd_ep->ed == NULL) {
+		free(hcd_ep);
+		return NULL;
+	}
+
+	hcd_ep->td = malloc32(sizeof(td_t));
+	if (hcd_ep->td == NULL) {
+		free32(hcd_ep->ed);
+		free(hcd_ep);
+		return NULL;
+	}
+
+	ed_init(hcd_ep->ed, ep);
+	ed_set_td(hcd_ep->ed, hcd_ep->td);
+	endpoint_set_hc_data(ep, hcd_ep, hcd_ep_toggle_get, hcd_ep_toggle_set);
+
+	return hcd_ep;
+}
+/*----------------------------------------------------------------------------*/
+/** Disposes assigned hcd endpoint structure
+ *
+ * @param[in] ep USBD endpoint structure
+ */
+void hcd_endpoint_clear(endpoint_t *ep)
+{
+	assert(ep);
+	hcd_endpoint_t *hcd_ep = ep->hc_data.data;
+	assert(hcd_ep);
+	free32(hcd_ep->ed);
+	free32(hcd_ep->td);
+	free(hcd_ep);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hcd_endpoint.h
===================================================================
--- uspace/drv/bus/usb/ohci/hcd_endpoint.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hcd_endpoint.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HCD_ENDPOINT_H
+#define DRV_OHCI_HCD_ENDPOINT_H
+
+#include <assert.h>
+#include <adt/list.h>
+#include <usb/host/endpoint.h>
+
+#include "hw_struct/endpoint_descriptor.h"
+#include "hw_struct/transfer_descriptor.h"
+
+/** Connector structure linking ED to to prepared TD. */
+typedef struct hcd_endpoint {
+	/** OHCI endpoint descriptor */
+	ed_t *ed;
+	/** Currently enqueued transfer descriptor */
+	td_t *td;
+	/** Linked list used by driver software */
+	link_t link;
+} hcd_endpoint_t;
+
+hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
+void hcd_endpoint_clear(endpoint_t *ep);
+
+/** Get and convert assigned hcd_endpoint_t structure
+ * @param[in] ep USBD endpoint structure.
+ * @return Pointer to assigned hcd endpoint structure
+ */
+static inline hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)
+{
+	assert(ep);
+	return ep->hc_data.data;
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H
+#define DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H
+
+#include <errno.h>
+
+#define CC_NOERROR (0x0)
+#define CC_CRC (0x1)
+#define CC_BITSTUFF (0x2)
+#define CC_TOGGLE (0x3)
+#define CC_STALL (0x4)
+#define CC_NORESPONSE (0x5)
+#define CC_PIDFAIL (0x6)
+#define CC_PIDUNEXPECTED (0x7)
+#define CC_DATAOVERRRUN (0x8)
+#define CC_DATAUNDERRRUN (0x9)
+#define CC_BUFFEROVERRRUN (0xc)
+#define CC_BUFFERUNDERRUN (0xd)
+#define CC_NOACCESS1 (0xe)
+#define CC_NOACCESS2 (0xf)
+
+inline static int cc_to_rc(int cc)
+{
+	switch (cc) {
+	case CC_NOERROR:
+		return EOK;
+
+	case CC_CRC:
+		return EBADCHECKSUM;
+
+	case CC_PIDUNEXPECTED:
+	case CC_PIDFAIL:
+	case CC_BITSTUFF:
+		return EIO;
+
+	case CC_TOGGLE:
+	case CC_STALL:
+		return ESTALL;
+
+	case CC_NORESPONSE:
+		return ETIMEOUT;
+
+	case CC_DATAOVERRRUN:
+	case CC_DATAUNDERRRUN:
+	case CC_BUFFEROVERRRUN:
+	case CC_BUFFERUNDERRUN:
+		return EOVERFLOW;
+
+	case CC_NOACCESS1:
+	case CC_NOACCESS2:
+	default:
+		return ENOTSUP;
+	}
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include "endpoint_descriptor.h"
+
+static unsigned direc[3] =
+    { ED_STATUS_D_IN, ED_STATUS_D_OUT, ED_STATUS_D_TRANSFER };
+
+void ed_init(ed_t *instance, endpoint_t *ep)
+{
+	assert(instance);
+	bzero(instance, sizeof(ed_t));
+	if (ep == NULL) {
+		instance->status = ED_STATUS_K_FLAG;
+		return;
+	}
+	assert(ep);
+	instance->status = 0
+	    | ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
+	    | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)
+	    | ((direc[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)
+	    | ((ep->max_packet_size & ED_STATUS_MPS_MASK)
+	        << ED_STATUS_MPS_SHIFT);
+
+
+	if (ep->speed == USB_SPEED_LOW)
+		instance->status |= ED_STATUS_S_FLAG;
+	if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
+		instance->status |= ED_STATUS_F_FLAG;
+
+	if (ep->toggle)
+		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
+#define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <usb/host/endpoint.h>
+
+#include "../utils/malloc32.h"
+#include "transfer_descriptor.h"
+
+#include "completion_codes.h"
+
+typedef struct ed {
+	volatile uint32_t status;
+#define ED_STATUS_FA_MASK (0x7f)   /* USB device address   */
+#define ED_STATUS_FA_SHIFT (0)
+#define ED_STATUS_EN_MASK (0xf)    /* USB endpoint address */
+#define ED_STATUS_EN_SHIFT (7)
+#define ED_STATUS_D_MASK (0x3)     /* direction */
+#define ED_STATUS_D_SHIFT (11)
+#define ED_STATUS_D_OUT (0x1)
+#define ED_STATUS_D_IN (0x2)
+#define ED_STATUS_D_TRANSFER (0x3)
+
+#define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */
+#define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */
+#define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/
+#define ED_STATUS_MPS_MASK (0x3ff) /* max_packet_size*/
+#define ED_STATUS_MPS_SHIFT (16)
+
+	volatile uint32_t td_tail;
+#define ED_TDTAIL_PTR_MASK (0xfffffff0)
+#define ED_TDTAIL_PTR_SHIFT (0)
+
+	volatile uint32_t td_head;
+#define ED_TDHEAD_PTR_MASK (0xfffffff0)
+#define ED_TDHEAD_PTR_SHIFT (0)
+#define ED_TDHEAD_ZERO_MASK (0x3)
+#define ED_TDHEAD_ZERO_SHIFT (2)
+#define ED_TDHEAD_TOGGLE_CARRY (0x2)
+#define ED_TDHEAD_HALTED_FLAG (0x1)
+
+	volatile uint32_t next;
+#define ED_NEXT_PTR_MASK (0xfffffff0)
+#define ED_NEXT_PTR_SHIFT (0)
+} __attribute__((packed)) ed_t;
+
+void ed_init(ed_t *instance, endpoint_t *ep);
+
+static inline void ed_set_td(ed_t *instance, td_t *td)
+{
+	assert(instance);
+	uintptr_t pa = addr_to_phys(td);
+	instance->td_head =
+	    ((pa & ED_TDHEAD_PTR_MASK)
+	    | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
+	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+}
+
+static inline void ed_set_end_td(ed_t *instance, td_t *td)
+{
+	assert(instance);
+	uintptr_t pa = addr_to_phys(td);
+	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+}
+
+static inline void ed_append_ed(ed_t *instance, ed_t *next)
+{
+	assert(instance);
+	assert(next);
+	uint32_t pa = addr_to_phys(next);
+	assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);
+	instance->next = pa;
+}
+
+static inline int ed_toggle_get(ed_t *instance)
+{
+	assert(instance);
+	return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
+}
+
+static inline void ed_toggle_set(ed_t *instance, int toggle)
+{
+	assert(instance);
+	assert(toggle == 0 || toggle == 1);
+	if (toggle == 1) {
+		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+	} else {
+		/* clear halted flag when reseting toggle */
+		instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
+		instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+	}
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hw_struct/hcca.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_HCCA_H
+#define DRV_OHCI_HW_STRUCT_HCCA_H
+
+#include <stdint.h>
+
+/** Host controller communication area.
+ * Shared memory used for communication between the controller and the driver.
+ */
+typedef struct hcca {
+	uint32_t int_ep[32];
+	uint16_t frame_number;
+	uint16_t pad1;
+	uint32_t done_head;
+	uint32_t reserved[29];
+} __attribute__((packed, aligned)) hcca_t;
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H
+#define DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H
+
+#include <stdint.h>
+
+#include "completion_codes.h"
+
+typedef struct itd {
+	volatile uint32_t status;
+#define ITD_STATUS_SF_MASK (0xffff) /* starting frame */
+#define ITD_STATUS_SF_SHIFT (0)
+#define ITD_STATUS_DI_MASK (0x7) /* delay int, wait DI frames before int */
+#define ITD_STATUS_DI_SHIFT (21)
+#define ITD_STATUS_DI_NO_INTERRUPT (0x7)
+#define ITD_STATUS_FC_MASK (0x7) /* frame count */
+#define ITD_STATUS_FC_SHIFT (24)
+#define ITD_STATUS_CC_MASK (0xf) /* condition code */
+#define ITD_STATUS_CC_SHIFT (28)
+
+	volatile uint32_t page;   /* page number of the first byte in buffer */
+#define ITD_PAGE_BP0_MASK (0xfffff000)
+#define ITD_PAGE_BP0_SHIFT (0)
+
+	volatile uint32_t next;
+#define ITD_NEXT_PTR_MASK (0xfffffff0)
+#define ITD_NEXT_PTR_SHIFT (0)
+
+	volatile uint32_t be; /* buffer end, address of the last byte */
+
+	volatile uint16_t offset[8];
+#define ITD_OFFSET_SIZE_MASK (0x3ff)
+#define ITD_OFFSET_SIZE_SHIFT (0)
+#define ITD_OFFSET_CC_MASK (0xf)
+#define ITD_OFFSET_CC_SHIFT (12)
+
+} __attribute__((packed)) itd_t;
+#endif
+/**
+ * @}
+ */
+
+
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include <usb/usb.h>
+#include "transfer_descriptor.h"
+
+static unsigned dp[3] =
+    { TD_STATUS_DP_IN, TD_STATUS_DP_OUT, TD_STATUS_DP_SETUP };
+static unsigned togg[2] = { TD_STATUS_T_0, TD_STATUS_T_1 };
+
+void td_init(
+    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle)
+{
+	assert(instance);
+	bzero(instance, sizeof(td_t));
+	instance->status = 0
+	    | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
+	    | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
+	if (toggle == 0 || toggle == 1) {
+		instance->status |= togg[toggle] << TD_STATUS_T_SHIFT;
+	}
+	if (dir == USB_DIRECTION_IN) {
+		instance->status |= TD_STATUS_ROUND_FLAG;
+	}
+	if (buffer != NULL) {
+		assert(size != 0);
+		instance->cbp = addr_to_phys(buffer);
+		instance->be = addr_to_phys(buffer + size - 1);
+	}
+}
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
+#define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
+
+#include <bool.h>
+#include <stdint.h>
+#include "../utils/malloc32.h"
+
+#include "completion_codes.h"
+
+/* OHCI TDs can handle up to 8KB buffers, however, it can use max 2 pages.
+ * Using 4KB buffers guarantees the page count condition.
+ * (OHCI assumes 4KB pages) */
+#define OHCI_TD_MAX_TRANSFER (4 * 1024)
+
+typedef struct td {
+	volatile uint32_t status;
+#define TD_STATUS_ROUND_FLAG (1 << 18)
+#define TD_STATUS_DP_MASK (0x3) /* direction/PID */
+#define TD_STATUS_DP_SHIFT (19)
+#define TD_STATUS_DP_SETUP (0x0)
+#define TD_STATUS_DP_OUT (0x1)
+#define TD_STATUS_DP_IN (0x2)
+#define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */
+#define TD_STATUS_DI_SHIFT (21)
+#define TD_STATUS_DI_NO_INTERRUPT (0x7)
+#define TD_STATUS_T_MASK (0x3)  /* data toggle 1x = use ED toggle carry */
+#define TD_STATUS_T_SHIFT (24)
+#define TD_STATUS_T_0 (0x2)
+#define TD_STATUS_T_1 (0x3)
+#define TD_STATUS_T_ED (0)
+#define TD_STATUS_EC_MASK (0x3) /* error count */
+#define TD_STATUS_EC_SHIFT (26)
+#define TD_STATUS_CC_MASK (0xf) /* condition code */
+#define TD_STATUS_CC_SHIFT (28)
+
+	volatile uint32_t cbp; /* current buffer ptr, data to be transfered */
+	volatile uint32_t next;
+#define TD_NEXT_PTR_MASK (0xfffffff0)
+#define TD_NEXT_PTR_SHIFT (0)
+
+	volatile uint32_t be; /* buffer end, address of the last byte */
+} __attribute__((packed)) td_t;
+
+void td_init(
+    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);
+
+inline static void td_set_next(td_t *instance, td_t *next)
+{
+	assert(instance);
+	instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
+}
+
+inline static bool td_is_finished(td_t *instance)
+{
+	assert(instance);
+	int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
+	/* something went wrong, error code is set */
+	if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
+		return true;
+	}
+	/* everything done */
+	if (cc == CC_NOERROR && instance->cbp == 0) {
+		return true;
+	}
+	return false;
+}
+
+static inline int td_error(td_t *instance)
+{
+	assert(instance);
+	int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
+	return cc_to_rc(cc);
+}
+
+static inline size_t td_remain_size(td_t *instance)
+{
+	assert(instance);
+	if (instance->cbp == 0)
+		return 0;
+	return instance->be - instance->cbp + 1;
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/iface.c
===================================================================
--- uspace/drv/bus/usb/ohci/iface.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/iface.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver hc interface implementation
+ */
+#include <ddf/driver.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+#include <usb/host/endpoint.h>
+
+#include "iface.h"
+#include "hc.h"
+
+static inline int setup_batch(
+    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
+    void *data, size_t size, void * setup_data, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t in,
+    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
+    hc_t **hc, usb_transfer_batch_t **batch)
+{
+	assert(hc);
+	assert(batch);
+	assert(fun);
+	*hc = fun_to_hc(fun);
+	assert(*hc);
+
+	size_t res_bw;
+	endpoint_t *ep = hc_get_endpoint(*hc,
+	    target.address, target.endpoint, direction, &res_bw);
+	if (ep == NULL) {
+		usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
+		    target.address, target.endpoint, name);
+		return ENOENT;
+	}
+
+	usb_log_debug("%s %d:%d %zu(%zu).\n",
+	    name, target.address, target.endpoint, size, ep->max_packet_size);
+
+	const size_t bw = bandwidth_count_usb11(
+	    ep->speed, ep->transfer_type, size, ep->max_packet_size);
+	if (res_bw < bw) {
+		usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
+		    "but only %zu is reserved.\n",
+		    target.address, target.endpoint, name, bw, res_bw);
+		return ENOSPC;
+	}
+
+	*batch = batch_get(
+	    fun, ep, data, size, setup_data, setup_size, in, out, arg);
+	if (!*batch)
+		return ENOMEM;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Request address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] speed Speed to associate with the new default address.
+ * @param[out] address Place to write a new address.
+ * @return Error code.
+ */
+static int request_address(
+    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	assert(address);
+
+	usb_log_debug("Address request with speed %d.\n", speed);
+	*address = device_keeper_get_free_address(&hc->manager, speed);
+	usb_log_debug("Address request with result: %d.\n", *address);
+	if (*address <= 0)
+		return *address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Bind address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address of the device
+ * @param[in] handle Devman handle of the device driver.
+ * @return Error code.
+ */
+static int bind_address(
+  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
+	usb_device_keeper_bind(&hc->manager, address, handle);
+	return EOK;
+}
+
+
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	bool found =
+	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
+	return found ? EOK : ENOENT;
+}
+
+/*----------------------------------------------------------------------------*/
+/** Release address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address release %d.\n", address);
+	usb_device_keeper_release(&hc->manager, address);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Register endpoint for bandwidth reservation.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] ep_speed Endpoint speed (invalid means to use device one).
+ * @param[in] endpoint Endpoint number.
+ * @param[in] transfer_type USB transfer type.
+ * @param[in] direction Endpoint data direction.
+ * @param[in] max_packet_size Max packet size of the endpoint.
+ * @param[in] interval Polling interval.
+ * @return Error code.
+ */
+static int register_endpoint(ddf_fun_t *fun,
+    usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+
+	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
+	if (speed >= USB_SPEED_MAX) {
+		speed = ep_speed;
+	}
+	const size_t size = max_packet_size;
+
+	usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
+	    address, endpoint, usb_str_transfer_type(transfer_type),
+	    usb_str_speed(speed), direction, size, max_packet_size, interval);
+
+	return hc_add_endpoint(hc, address, endpoint, speed, transfer_type,
+	    direction, max_packet_size, size, interval);
+}
+/*----------------------------------------------------------------------------*/
+static int unregister_endpoint(
+    ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Unregister endpoint %d:%d %d.\n",
+	    address, endpoint, direction);
+	return hc_remove_endpoint(hc, address, endpoint, direction);
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule interrupt out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_out(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
+	    NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_interrupt_out(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule interrupt in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_in(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
+	    NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_interrupt_in(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule bulk out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_out(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
+	    NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_bulk_out(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule bulk in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_in(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
+	    NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_bulk_in(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule control write transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Data buffer (in USB endianess, allocated and
+ *	deallocated by the caller).
+ * @param[in] size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_write(
+    ddf_fun_t *fun, 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)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
+	    setup_data, setup_size, NULL, callback, arg, "Control WRITE",
+	    &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
+	batch_control_write(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule control read transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_read(
+    ddf_fun_t *fun, 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)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
+	    setup_data, setup_size, callback, NULL, arg, "Control READ",
+	    &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_control_read(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+usbhc_iface_t hc_iface = {
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.find_by_address = find_by_address,
+	.release_address = release_address,
+
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.bulk_out = bulk_out,
+	.bulk_in = bulk_in,
+
+	.control_write = control_write,
+	.control_read = control_read,
+};
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/iface.h
===================================================================
--- uspace/drv/bus/usb/ohci/iface.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/iface.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,45 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * Common OHCI definitions.
+ */
+#ifndef DRV_OHCI_IFACE_H
+#define DRV_OHCI_IFACE_H
+
+#include <usbhc_iface.h>
+
+extern usbhc_iface_t hc_iface;
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/main.c
===================================================================
--- uspace/drv/bus/usb/ohci/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * Main routines of OHCI driver.
+ */
+#include <ddf/driver.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/debug.h>
+
+#include "ohci.h"
+
+#define NAME "ohci"
+
+/** Initializes a new ddf driver instance of OHCI hcd.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int ohci_add_device(ddf_dev_t *device)
+{
+	usb_log_debug("ohci_add_device() called\n");
+	assert(device);
+
+	int ret = device_setup_ohci(device);
+	if (ret != EOK) {
+		usb_log_error("Failed to initialize OHCI driver: %s.\n",
+		    str_error(ret));
+		return ret;
+	}
+	usb_log_info("Controlling new OHCI device '%s'.\n", device->name);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static driver_ops_t ohci_driver_ops = {
+	.add_device = ohci_add_device,
+};
+/*----------------------------------------------------------------------------*/
+static driver_t ohci_driver = {
+	.name = NAME,
+	.driver_ops = &ohci_driver_ops
+};
+/*----------------------------------------------------------------------------*/
+/** Initializes global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	return ddf_driver_main(&ohci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/interrupt.h>
+#include <usb_iface.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "ohci.h"
+#include "iface.h"
+#include "pci.h"
+#include "hc.h"
+#include "root_hub.h"
+
+typedef struct ohci {
+	ddf_fun_t *hc_fun;
+	ddf_fun_t *rh_fun;
+
+	hc_t hc;
+	rh_t rh;
+} ohci_t;
+
+static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
+{
+	assert(dev);
+	assert(dev->driver_data);
+	return dev->driver_data;
+}
+
+/** IRQ handling callback, identifies device
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
+static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	hc_t *hc = &dev_to_ohci(dev)->hc;
+	assert(hc);
+	const uint16_t status = IPC_GET_ARG1(*call);
+	hc_interrupt(hc, status);
+}
+/*----------------------------------------------------------------------------*/
+/** Get address of the device identified by handle.
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
+static int usb_iface_get_address(
+    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
+{
+	assert(fun);
+	usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager;
+
+	usb_address_t addr = usb_device_keeper_find(manager, handle);
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Gets handle of the respective hc (this device, hc function).
+ *
+ * @param[in] root_hub_fun Root hub function seeking hc handle.
+ * @param[out] handle Place to write the handle.
+ * @return Error code.
+ */
+static int usb_iface_get_hc_handle(
+    ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+	ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
+	assert(hc_fun);
+
+	if (handle != NULL)
+		*handle = hc_fun->handle;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Root hub USB interface */
+static usb_iface_t usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle,
+	.get_address = usb_iface_get_address
+};
+/*----------------------------------------------------------------------------*/
+/** Standard USB HC options (HC interface) */
+static ddf_dev_ops_t hc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
+};
+/*----------------------------------------------------------------------------*/
+/** Standard USB RH options (RH interface) */
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface,
+};
+/*----------------------------------------------------------------------------*/
+/** Initialize hc and rh ddf structures and their respective drivers.
+ *
+ * @param[in] device DDF instance of the device to use.
+ * @param[in] instance OHCI structure to use.
+ *
+ * This function does all the preparatory work for hc and rh drivers:
+ *  - gets device hw resources
+ *  - disables OHCI legacy support
+ *  - asks for interrupt
+ *  - registers interrupt handler
+ */
+int device_setup_ohci(ddf_dev_t *device)
+{
+	ohci_t *instance = malloc(sizeof(ohci_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate OHCI driver.\n");
+		return ENOMEM;
+	}
+
+#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+if (ret != EOK) { \
+	if (instance->hc_fun) { \
+		instance->hc_fun->ops = NULL; \
+		instance->hc_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->hc_fun); \
+	} \
+	if (instance->rh_fun) { \
+		instance->rh_fun->ops = NULL; \
+		instance->rh_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->rh_fun); \
+	} \
+	free(instance); \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
+
+	instance->rh_fun = NULL;
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
+	int ret = instance->hc_fun ? EOK : ENOMEM;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n");
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
+	ret = instance->rh_fun ? EOK : ENOMEM;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n");
+	instance->rh_fun->ops = &rh_ops;
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
+	int irq = 0;
+
+	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to get memory addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
+	    (void *) reg_base, reg_size, irq);
+
+	bool interrupts = false;
+#ifdef CONFIG_USBHC_NO_INTERRUPTS
+	usb_log_warning("Interrupts disabled in OS config, "
+	    "falling back to polling.\n");
+#else
+	ret = pci_enable_interrupts(device);
+	if (ret != EOK) {
+		usb_log_warning("Failed to enable interrupts: %s.\n",
+		    str_error(ret));
+		usb_log_info("HW interrupts not available, "
+		    "falling back to polling.\n");
+	} else {
+		usb_log_debug("Hw interrupts enabled.\n");
+		interrupts = true;
+	}
+#endif
+
+	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci_hcd.\n", ret);
+
+#define CHECK_RET_FINI_RETURN(ret, message...) \
+if (ret != EOK) { \
+	hc_fini(&instance->hc); \
+	CHECK_RET_DEST_FREE_RETURN(ret, message); \
+} else (void)0
+
+	/* It does no harm if we register this on polling */
+	ret = register_interrupt_handler(device, irq, irq_handler,
+	    &instance->hc.interrupt_code);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to register interrupt handler.\n", ret);
+
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to bind OHCI device function: %s.\n",
+	    ret, str_error(ret));
+
+	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
+
+	device->driver_data = instance;
+
+	hc_start_hw(&instance->hc);
+	hc_register_hub(&instance->hc, instance->rh_fun);
+	return EOK;
+
+#undef CHECK_RET_DEST_FUN_RETURN
+#undef CHECK_RET_FINI_RETURN
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/ohci.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/ohci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver main structure for both host controller and root-hub.
+ */
+#ifndef DRV_OHCI_OHCI_H
+#define DRV_OHCI_OHCI_H
+#include <ddi.h>
+#include <ddf/driver.h>
+
+int device_setup_ohci(ddf_dev_t *device);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/ohci.ma
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/ohci.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,15 @@
+10 pci/ven=106b&dev=0026
+10 pci/ven=106b&dev=003f
+10 pci/ven=10de&dev=0aa5
+
+10 pci/ven=1002&dev=4374
+10 pci/ven=1002&dev=4375
+
+10 pci/ven=1002&dev=4387
+10 pci/ven=1002&dev=4388
+10 pci/ven=1002&dev=4389
+10 pci/ven=1002&dev=438a
+10 pci/ven=1002&dev=438b
+10 pci/ven=1002&dev=4397
+10 pci/ven=1002&dev=4398
+10 pci/ven=1002&dev=4399
Index: uspace/drv/bus/usb/ohci/ohci_regs.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_regs.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/ohci_regs.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,219 @@
+/*
+ * 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 drvusbohcihc
+ * @{
+ */
+/** @file
+ * @brief OHCI host controller register structure
+ */
+#ifndef DRV_OHCI_OHCI_REGS_H
+#define DRV_OHCI_OHCI_REGS_H
+#include <stdint.h>
+
+/** OHCI memory mapped registers structure */
+typedef struct ohci_regs {
+	const volatile uint32_t revision;
+	volatile uint32_t control;
+#define C_CSBR_MASK (0x3) /* Control-bulk service ratio */
+#define C_CSBR_1_1  (0x0)
+#define C_CSBR_1_2  (0x1)
+#define C_CSBR_1_3  (0x2)
+#define C_CSBR_1_4  (0x3)
+#define C_CSBR_SHIFT (0)
+
+#define C_PLE (1 << 2)   /* Periodic list enable */
+#define C_IE  (1 << 3)   /* Isochronous enable */
+#define C_CLE (1 << 4)   /* Control list enable */
+#define C_BLE (1 << 5)   /* Bulk list enable */
+
+#define C_HCFS_MASK        (0x3) /* Host controller functional state */
+#define C_HCFS_RESET       (0x0)
+#define C_HCFS_RESUME      (0x1)
+#define C_HCFS_OPERATIONAL (0x2)
+#define C_HCFS_SUSPEND     (0x3)
+#define C_HCFS_SHIFT       (6)
+
+#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
+#define C_RWC (1 << 9)   /* Remote wakeup connected, host specific */
+#define C_RWE (1 << 10)  /* Remote wakeup enable */
+
+	volatile uint32_t command_status;
+#define CS_HCR (1 << 0)   /* Host controller reset */
+#define CS_CLF (1 << 1)   /* Control list filled */
+#define CS_BLF (1 << 2)   /* Bulk list filled */
+#define CS_OCR (1 << 3)   /* Ownership change request */
+#define CS_SOC_MASK (0x3) /* Scheduling overrun count */
+#define CS_SOC_SHIFT (16)
+
+	/** Interupt enable/disable/status,
+	 * reads give the same value,
+	 * writing causes enable/disable,
+	 * status is write-clean (writing 1 clears the bit*/
+	volatile uint32_t interrupt_status;
+	volatile uint32_t interrupt_enable;
+	volatile uint32_t interrupt_disable;
+#define I_SO   (1 << 0)   /* Scheduling overrun */
+#define I_WDH  (1 << 1)   /* Done head write-back */
+#define I_SF   (1 << 2)   /* Start of frame */
+#define I_RD   (1 << 3)   /* Resume detect */
+#define I_UE   (1 << 4)   /* Unrecoverable error */
+#define I_FNO  (1 << 5)   /* Frame number overflow */
+#define I_RHSC (1 << 6)   /* Root hub status change */
+#define I_OC   (1 << 30)  /* Ownership change */
+#define I_MI   (1 << 31)  /* Master interrupt (all/any interrupts) */
+
+	/** HCCA pointer (see hw_struct hcca.h) */
+	volatile uint32_t hcca;
+#define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
+
+	/** Currently executed periodic endpoint */
+	const volatile uint32_t periodic_current;
+
+	/** The first control endpoint */
+	volatile uint32_t control_head;
+
+	/** Currently executed control endpoint */
+	volatile uint32_t control_current;
+
+	/** The first bulk endpoint */
+	volatile uint32_t bulk_head;
+
+	/** Currently executed bulk endpoint */
+	volatile uint32_t bulk_current;
+
+	/** Done TD list, this value is periodically written to HCCA */
+	const volatile uint32_t done_head;
+
+	/** Frame time and max packet size for all transfers */
+	volatile uint32_t fm_interval;
+#define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/
+#define FMI_FI_SHIFT (0)
+#define FMI_FSMPS_MASK (0x7fff) /* Full speed max packet size */
+#define FMI_FSMPS_SHIFT (16)
+#define FMI_TOGGLE_FLAG (1 << 31)
+
+	/** Bit times remaining in current frame */
+	const volatile uint32_t fm_remaining;
+#define FMR_FR_MASK FMI_FI_MASK
+#define FMR_FR_SHIFT FMI_FI_SHIFT
+#define FMR_TOGGLE_FLAG FMI_TOGGLE_FLAG
+
+	/** Frame number */
+	const volatile uint32_t fm_number;
+#define FMN_NUMBER_MASK (0xffff)
+
+	/** Remaining bit time in frame to start periodic transfers */
+	volatile uint32_t periodic_start;
+#define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
+
+	/** Threshold for starting LS transaction */
+	volatile uint32_t ls_threshold;
+#define LST_LST_MASK (0x7fff)
+
+	/** The first root hub control register */
+	volatile uint32_t rh_desc_a;
+#define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
+#define RHDA_NDS_SHIFT (0)
+#define RHDA_PSM_FLAG  (1 << 8)  /* Power switching mode: 0-global, 1-per port*/
+#define RHDA_NPS_FLAG  (1 << 9)  /* No power switch: 1-power on, 0-use PSM*/
+#define RHDA_DT_FLAG   (1 << 10) /* 1-Compound device, must be 0 */
+#define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */
+#define RHDA_NOCP      (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
+#define RHDA_POTPGT_MASK (0xff)  /* Power on to power good time */
+#define RHDA_POTPGT_SHIFT (24)
+
+	/** The other root hub control register */
+	volatile uint32_t rh_desc_b;
+#define RHDB_DR_MASK (0xffff) /* Device removable mask */
+#define RHDB_DR_SHIFT (0)
+#define RHDB_PCC_MASK (0xffff) /* Power control mask */
+#define RHDB_PCC_SHIFT (16)
+
+/* Port device removable status */
+#define RHDB_DR_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
+/* Port power control status: 1-per port power control, 0-global power switch */
+#define RHDB_PPC_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
+
+	/** Root hub status register */
+	volatile uint32_t rh_status;
+#define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
+                                * write: 0-no effect,
+                                *        1-turn off port power for ports
+                                *        specified in PPCM(RHDB), or all ports,
+                                *        if power is set globally */
+#define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */
+#define RHS_OCI_FLAG  (1 <<  1)/* Over-current indicator, if per-port: 0 */
+#define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC
+                                *       1-connect status change wakes HC
+                                * write: 1-set DRWE, 0-no effect */
+#define RHS_SET_DRWE RHS_DRWE_FLAG
+#define RHS_LPSC_FLAG (1 << 16)/* read: 0,
+                                * write: 0-no effect
+                                *        1-turn on port power for ports
+                                *        specified in PPCM(RHDB), or all ports,
+                                *        if power is set globally */
+#define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */
+#define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
+#define RHS_CLEAR_DRWE (1 << 31)
+
+	/** Root hub per port status */
+	volatile uint32_t rh_port_status[];
+#define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
+                                * w: 1-clear port enable, 0-nothing */
+#define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG
+#define RHPS_PES_FLAG (1 << 1) /* r: port enable status
+                                * w: 1-set port enable, 0-nothing */
+#define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG
+#define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status
+                                * w: 1-set port suspend, 0-nothing */
+#define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG
+#define RHPS_POCI_FLAG (1 << 3) /* r: port over-current (if reports are per-port
+                                 * w: 1-clear port suspend (start resume
+                                 *      if suspened)
+                                 *    0-nothing */
+#define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG
+#define RHPS_PRS_FLAG (1 << 4) /* r: port reset status
+                                * w: 1-set port reset, 0-nothing */
+#define RHPS_SET_PORT_RESET RHPS_PRS_FLAG
+#define RHPS_PPS_FLAG (1 << 8) /* r: port power status
+                                * w: 1-set port power, 0-nothing */
+#define RHPS_SET_PORT_POWER RHPS_PPS_FLAG
+#define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached
+                                 * w: 1-clear port power, 0-nothing */
+#define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG
+#define RHPS_CSC_FLAG  (1 << 16) /* connect status change Write-Clean */
+#define RHPS_PESC_FLAG (1 << 17) /* port enable status change WC */
+#define RHPS_PSSC_FLAG (1 << 18) /* port suspend status change WC */
+#define RHPS_OCIC_FLAG (1 << 19) /* port over-current change WC */
+#define RHPS_PRSC_FLAG (1 << 20) /* port reset status change WC */
+#define RHPS_CHANGE_WC_MASK 0x1f0000
+} __attribute__((packed)) ohci_regs_t;
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/pci.c
===================================================================
--- uspace/drv/bus/usb/ohci/pci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/pci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup drvusbohci
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the OHCI driver.
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include <as.h>
+#include <devman.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <device/hw_res.h>
+
+#include <usb/debug.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+/** Get address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] mem_reg_address Base address of the memory range.
+ * @param[out] mem_reg_size Size of the memory range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(ddf_dev_t *dev,
+    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
+{
+	assert(dev);
+	assert(mem_reg_address);
+	assert(mem_reg_size);
+	assert(irq_no);
+
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	hw_resource_list_t hw_resources;
+	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (rc != EOK) {
+		async_hangup(parent_sess);
+		return rc;
+	}
+	
+	uintptr_t mem_address = 0;
+	size_t mem_size = 0;
+	bool mem_found = false;
+	
+	int irq = 0;
+	bool irq_found = false;
+	
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			irq = res->res.interrupt.irq;
+			irq_found = true;
+			usb_log_debug2("Found interrupt: %d.\n", irq);
+			break;
+		case MEM_RANGE:
+			if (res->res.mem_range.address != 0
+			    && res->res.mem_range.size != 0 ) {
+				mem_address = res->res.mem_range.address;
+				mem_size = res->res.mem_range.size;
+				usb_log_debug2("Found mem: %p %zu.\n",
+				    (void *) mem_address, mem_size);
+				mem_found = true;
+			}
+		default:
+			break;
+		}
+	}
+	
+	if (mem_found && irq_found) {
+		*mem_reg_address = mem_address;
+		*mem_reg_size = mem_size;
+		*irq_no = irq;
+		rc = EOK;
+	} else
+		rc = ENOENT;
+	
+	async_hangup(parent_sess);
+	return rc;
+}
+
+/** Call the PCI driver with a request to enable interrupts
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_enable_interrupts(ddf_dev_t *device)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	bool enabled = hw_res_enable_interrupt(parent_sess);
+	async_hangup(parent_sess);
+	
+	return enabled ? EOK : EIO;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/pci.h
===================================================================
--- uspace/drv/bus/usb/ohci/pci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/pci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,47 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * PCI related functions needed by OHCI driver.
+ */
+#ifndef DRV_OHCI_PCI_H
+#define DRV_OHCI_PCI_H
+
+#include <ddf/driver.h>
+
+int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(ddf_dev_t *);
+int pci_disable_legacy(ddf_dev_t *);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/root_hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,941 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/debug.h>
+
+#include "root_hub.h"
+#include <usb/classes/classes.h>
+#include <usb/dev/driver.h>
+#include "ohci_regs.h"
+
+#include <usb/dev/request.h>
+#include <usb/classes/hub.h>
+
+/**
+ * standart device descriptor for ohci root hub
+ */
+static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = {
+	.configuration_count = 1,
+	.descriptor_type = USB_DESCTYPE_DEVICE,
+	.device_class = USB_CLASS_HUB,
+	.device_protocol = 0,
+	.device_subclass = 0,
+	.device_version = 0,
+	.length = sizeof (usb_standard_device_descriptor_t),
+	.max_packet_size = 8,
+	.vendor_id = 0x16db,
+	.product_id = 0x0001,
+	.str_serial_number = 0,
+	.usb_spec_version = 0x110,
+};
+
+/**
+ * standart configuration descriptor with filled common values
+ * for ohci root hubs
+ */
+static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = {
+	.attributes = 1 << 7,
+	.configuration_number = 1,
+	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
+	.interface_count = 1,
+	.length = sizeof (usb_standard_configuration_descriptor_t),
+	.max_power = 100,
+	.str_configuration = 0,
+};
+
+/**
+ * standart ohci root hub interface descriptor
+ */
+static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = {
+	.alternate_setting = 0,
+	.descriptor_type = USB_DESCTYPE_INTERFACE,
+	.endpoint_count = 1,
+	.interface_class = USB_CLASS_HUB,
+	.interface_number = 1,
+	.interface_protocol = 0,
+	.interface_subclass = 0,
+	.length = sizeof (usb_standard_interface_descriptor_t),
+	.str_interface = 0,
+};
+
+/**
+ * standart ohci root hub endpoint descriptor
+ */
+static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = {
+	.attributes = USB_TRANSFER_INTERRUPT,
+	.descriptor_type = USB_DESCTYPE_ENDPOINT,
+	.endpoint_address = 1 + (1 << 7),
+	.length = sizeof (usb_standard_endpoint_descriptor_t),
+	.max_packet_size = 8,
+	.poll_interval = 255,
+};
+
+/**
+ * bitmask of hub features that are valid to be cleared
+ */
+static const uint32_t hub_clear_feature_valid_mask =
+    RHS_OCIC_FLAG |
+    RHS_CLEAR_PORT_POWER;
+
+/**
+ * bitmask of hub features that are cleared by writing 1 (and not 0)
+ */
+static const uint32_t hub_clear_feature_by_writing_one_mask =
+    RHS_CLEAR_PORT_POWER;
+
+/**
+ * bitmask of hub features that are valid to be set
+ */
+static const uint32_t hub_set_feature_valid_mask =
+    RHS_LPSC_FLAG |
+    RHS_OCIC_FLAG;
+
+/**
+ * bitmask of hub features that are set by writing 1 and cleared by writing 0
+ */
+static const uint32_t hub_set_feature_direct_mask =
+    RHS_SET_PORT_POWER;
+
+/**
+ * bitmask of port features that are valid to be set
+ */
+static const uint32_t port_set_feature_valid_mask =
+    RHPS_SET_PORT_ENABLE |
+    RHPS_SET_PORT_SUSPEND |
+    RHPS_SET_PORT_RESET |
+    RHPS_SET_PORT_POWER;
+
+/**
+ * bitmask of port features that can be cleared
+ */
+static const uint32_t port_clear_feature_valid_mask =
+    RHPS_CCS_FLAG |
+    RHPS_SET_PORT_SUSPEND |
+    RHPS_POCI_FLAG |
+    RHPS_SET_PORT_POWER |
+    RHPS_CSC_FLAG |
+    RHPS_PESC_FLAG |
+    RHPS_PSSC_FLAG |
+    RHPS_OCIC_FLAG |
+    RHPS_PRSC_FLAG;
+
+//note that USB_HUB_FEATURE_PORT_POWER bit is translated into
+//USB_HUB_FEATURE_PORT_LOW_SPEED for port set feature request
+
+/**
+ * bitmask with port status changes
+ */
+static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK;
+
+static int create_serialized_hub_descriptor(rh_t *instance);
+
+static int rh_init_descriptors(rh_t *instance);
+
+static int process_get_port_status_request(rh_t *instance, uint16_t port,
+    usb_transfer_batch_t * request);
+
+static int process_get_hub_status_request(rh_t *instance,
+    usb_transfer_batch_t * request);
+
+static int process_get_status_request(rh_t *instance,
+    usb_transfer_batch_t * request);
+
+static void create_interrupt_mask_in_instance(rh_t *instance);
+
+static int process_get_descriptor_request(rh_t *instance,
+    usb_transfer_batch_t *request);
+
+static int process_get_configuration_request(rh_t *instance,
+    usb_transfer_batch_t *request);
+
+static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
+
+static int process_hub_feature_clear_request(rh_t *instance,
+    uint16_t feature);
+
+static int process_port_feature_set_request(rh_t *instance,
+    uint16_t feature, uint16_t port);
+
+static int process_port_feature_clear_request(rh_t *instance,
+    uint16_t feature, uint16_t port);
+
+static int process_address_set_request(rh_t *instance,
+    uint16_t address);
+
+static int process_request_with_output(rh_t *instance,
+    usb_transfer_batch_t *request);
+
+static int process_request_with_input(rh_t *instance,
+    usb_transfer_batch_t *request);
+
+static int process_request_without_data(rh_t *instance,
+    usb_transfer_batch_t *request);
+
+static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
+
+static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
+
+static bool is_zeros(void * buffer, size_t size);
+
+/** Root hub initialization
+ * @return Error code.
+ */
+int rh_init(rh_t *instance, ohci_regs_t *regs) {
+	assert(instance);
+	instance->registers = regs;
+	instance->port_count =
+	    (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
+	int opResult = rh_init_descriptors(instance);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	// set port power mode to no-power-switching
+	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
+	instance->unfinished_interrupt_transfer = NULL;
+	instance->interrupt_mask_size = (instance->port_count + 8) / 8;
+	instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
+	if (!instance->interrupt_buffer)
+		return ENOMEM;
+
+	usb_log_info("Root hub (%zu ports) initialized.\n",
+	    instance->port_count);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process root hub request
+ *
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
+	assert(instance);
+	assert(request);
+	int opResult;
+	if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
+		usb_log_debug("Root hub got CONTROL packet\n");
+		opResult = process_ctrl_request(instance, request);
+		usb_transfer_batch_finish_error(request, opResult);
+	} else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
+		usb_log_debug("Root hub got INTERRUPT packet\n");
+		create_interrupt_mask_in_instance(instance);
+		if (is_zeros(instance->interrupt_buffer,
+		    instance->interrupt_mask_size)) {
+			usb_log_debug("No changes..\n");
+			instance->unfinished_interrupt_transfer = request;
+			//will be finished later
+		} else {
+			usb_log_debug("Processing changes..\n");
+			process_interrupt_mask_in_instance(instance, request);
+		}
+		opResult = EOK;
+	} else {
+
+		opResult = EINVAL;
+		usb_transfer_batch_finish_error(request, opResult);
+	}
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process interrupt on a hub
+ *
+ * If there is no pending interrupt transfer, nothing happens.
+ * @param instance
+ */
+void rh_interrupt(rh_t *instance) {
+	if (!instance->unfinished_interrupt_transfer) {
+		return;
+	}
+	usb_log_debug("Finalizing interrupt transfer\n");
+	create_interrupt_mask_in_instance(instance);
+	process_interrupt_mask_in_instance(instance,
+	    instance->unfinished_interrupt_transfer);
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Create hub descriptor used in hub-driver <-> hub communication
+ *
+ * This means creating byt array from data in root hub registers. For more
+ * info see usb hub specification.
+ *
+ * @param instance root hub instance
+ * @return error code
+ */
+static int create_serialized_hub_descriptor(rh_t *instance) {
+	size_t size = 7 +
+	    ((instance->port_count + 7) / 8) * 2;
+	size_t var_size = (instance->port_count + 7) / 8;
+	uint8_t * result = (uint8_t*) malloc(size);
+	if (!result) return ENOMEM;
+
+	bzero(result, size);
+	//size
+	result[0] = size;
+	//descriptor type
+	result[1] = USB_DESCTYPE_HUB;
+	result[2] = instance->port_count;
+	uint32_t hub_desc_reg = instance->registers->rh_desc_a;
+	result[3] =
+	    ((hub_desc_reg >> 8) % 2) +
+	    (((hub_desc_reg >> 9) % 2) << 1) +
+	    (((hub_desc_reg >> 10) % 2) << 2) +
+	    (((hub_desc_reg >> 11) % 2) << 3) +
+	    (((hub_desc_reg >> 12) % 2) << 4);
+	result[4] = 0;
+	result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
+	result[6] = 50;
+
+	size_t port;
+	for (port = 1; port <= instance->port_count; ++port) {
+		uint8_t is_non_removable =
+		    instance->registers->rh_desc_b >> port % 2;
+		result[7 + port / 8] +=
+		    is_non_removable << (port % 8);
+	}
+	size_t i;
+	for (i = 0; i < var_size; ++i) {
+		result[7 + var_size + i] = 255;
+	}
+	instance->hub_descriptor = result;
+	instance->descriptor_size = size;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/** initialize hub descriptors
+ *
+ * Initialized are device and full configuration descriptor. These need to
+ * be initialized only once per hub.
+ * @instance root hub instance
+ * @return error code
+ */
+static int rh_init_descriptors(rh_t *instance) {
+	memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
+	    sizeof (ohci_rh_device_descriptor)
+	    );
+	usb_standard_configuration_descriptor_t descriptor;
+	memcpy(&descriptor, &ohci_rh_conf_descriptor,
+	    sizeof (ohci_rh_conf_descriptor));
+
+	int opResult = create_serialized_hub_descriptor(instance);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	descriptor.total_length =
+	    sizeof (usb_standard_configuration_descriptor_t) +
+	    sizeof (usb_standard_endpoint_descriptor_t) +
+	    sizeof (usb_standard_interface_descriptor_t) +
+	    instance->descriptor_size;
+
+	uint8_t * full_config_descriptor =
+	    (uint8_t*) malloc(descriptor.total_length);
+	if (!full_config_descriptor) {
+		return ENOMEM;
+	}
+	memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
+	memcpy(full_config_descriptor + sizeof (descriptor),
+	    &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
+	memcpy(full_config_descriptor + sizeof (descriptor) +
+	    sizeof (ohci_rh_iface_descriptor),
+	    &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
+	memcpy(full_config_descriptor + sizeof (descriptor) +
+	    sizeof (ohci_rh_iface_descriptor) +
+	    sizeof (ohci_rh_ep_descriptor),
+	    instance->hub_descriptor, instance->descriptor_size);
+
+	instance->descriptors.configuration = full_config_descriptor;
+	instance->descriptors.configuration_size = descriptor.total_length;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * create answer to port status_request
+ *
+ * Copy content of corresponding port status register to answer buffer. The
+ * format of the port status register and port status data is the same (
+ * see OHCI root hub and USB hub documentation).
+ *
+ * @param instance root hub instance
+ * @param port port number, counted from 1
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_get_port_status_request(rh_t *instance, uint16_t port,
+    usb_transfer_batch_t * request) {
+	if (port < 1 || port > instance->port_count)
+		return EINVAL;
+	request->transfered_size = 4;
+	uint32_t data = instance->registers->rh_port_status[port - 1];
+	memcpy(request->data_buffer, &data, 4);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * create answer to port status_request
+ *
+ * This copies flags in hub status register into the buffer. The format of the
+ * status register and status message is the same, according to USB hub
+ * specification and OHCI root hub specification.
+ *
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_get_hub_status_request(rh_t *instance,
+    usb_transfer_batch_t * request) {
+	request->transfered_size = 4;
+	//bits, 0,1,16,17
+	uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
+	uint32_t data = mask & instance->registers->rh_status;
+	memcpy(request->data_buffer, &data, 4);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * create answer to status request
+ *
+ * This might be either hub status or port status request. If neither,
+ * ENOTSUP is returned.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_get_status_request(rh_t *instance,
+    usb_transfer_batch_t * request) {
+	size_t buffer_size = request->buffer_size;
+	usb_device_request_setup_packet_t * request_packet =
+	    (usb_device_request_setup_packet_t*)
+	    request->setup_buffer;
+
+	usb_hub_bm_request_type_t request_type = request_packet->request_type;
+	if (buffer_size < 4) {
+		usb_log_warning("Requested more data than buffer size\n");
+		return EINVAL;
+	}
+
+	if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
+		return process_get_hub_status_request(instance, request);
+	if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
+		return process_get_port_status_request(instance,
+	    request_packet->index,
+	    request);
+
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * create answer to status interrupt consisting of change bitmap
+ *
+ * Result contains bitmap where bit 0 indicates change on hub and
+ * bit i indicates change on i`th port (i>0). For more info see
+ * Hub and Port status bitmap specification in USB specification
+ * (chapter 11.13.4).
+ * Uses instance`s interrupt buffer to store the interrupt information.
+ * @param instance root hub instance
+ */
+static void create_interrupt_mask_in_instance(rh_t * instance) {
+	uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
+	uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
+	    | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
+	bzero(bitmap, instance->interrupt_mask_size);
+	if ((instance->registers->rh_status & mask) != 0) {
+		bitmap[0] = 1;
+	}
+	size_t port;
+	mask = port_status_change_mask;
+	for (port = 1; port <= instance->port_count; ++port) {
+		if ((mask & instance->registers->rh_port_status[port - 1]) != 0) {
+
+			bitmap[(port) / 8] += 1 << (port % 8);
+		}
+	}
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * create answer to a descriptor request
+ *
+ * This might be a request for standard (configuration, device, endpoint or
+ * interface) or device specific (hub) descriptor.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_get_descriptor_request(rh_t *instance,
+    usb_transfer_batch_t *request) {
+	usb_device_request_setup_packet_t * setup_request =
+	    (usb_device_request_setup_packet_t*) request->setup_buffer;
+	size_t size;
+	const void * result_descriptor = NULL;
+	const uint16_t setup_request_value = setup_request->value_high;
+	//(setup_request->value_low << 8);
+	switch (setup_request_value) {
+		case USB_DESCTYPE_HUB:
+		{
+			usb_log_debug2("USB_DESCTYPE_HUB\n");
+			result_descriptor = instance->hub_descriptor;
+			size = instance->descriptor_size;
+			break;
+		}
+		case USB_DESCTYPE_DEVICE:
+		{
+			usb_log_debug2("USB_DESCTYPE_DEVICE\n");
+			result_descriptor = &ohci_rh_device_descriptor;
+			size = sizeof (ohci_rh_device_descriptor);
+			break;
+		}
+		case USB_DESCTYPE_CONFIGURATION:
+		{
+			usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
+			result_descriptor = instance->descriptors.configuration;
+			size = instance->descriptors.configuration_size;
+			break;
+		}
+		case USB_DESCTYPE_INTERFACE:
+		{
+			usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
+			result_descriptor = &ohci_rh_iface_descriptor;
+			size = sizeof (ohci_rh_iface_descriptor);
+			break;
+		}
+		case USB_DESCTYPE_ENDPOINT:
+		{
+			usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
+			result_descriptor = &ohci_rh_ep_descriptor;
+			size = sizeof (ohci_rh_ep_descriptor);
+			break;
+		}
+		default:
+		{
+			usb_log_debug2("USB_DESCTYPE_EINVAL %d \n",
+			    setup_request->value);
+			usb_log_debug2("\ttype %d\n\trequest %d\n\tvalue "
+			    "%d\n\tindex %d\n\tlen %d\n ",
+			    setup_request->request_type,
+			    setup_request->request,
+			    setup_request_value,
+			    setup_request->index,
+			    setup_request->length
+			    );
+			return EINVAL;
+		}
+	}
+	if (request->buffer_size < size) {
+		size = request->buffer_size;
+	}
+	request->transfered_size = size;
+	memcpy(request->data_buffer, result_descriptor, size);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * answer to get configuration request
+ *
+ * Root hub works independently on the configuration.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_get_configuration_request(rh_t *instance,
+    usb_transfer_batch_t *request) {
+	//set and get configuration requests do not have any meaning, only dummy
+	//values are returned
+	if (request->buffer_size != 1)
+		return EINVAL;
+	request->data_buffer[0] = 1;
+	request->transfered_size = 1;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process feature-enabling request on hub
+ *
+ * @param instance root hub instance
+ * @param feature feature selector
+ * @return error code
+ */
+static int process_hub_feature_set_request(rh_t *instance,
+    uint16_t feature) {
+	if (!((1 << feature) & hub_set_feature_valid_mask))
+		return EINVAL;
+	if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
+		feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
+	instance->registers->rh_status =
+	    (instance->registers->rh_status | (1 << feature))
+	    & (~hub_clear_feature_by_writing_one_mask);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process feature-disabling request on hub
+ *
+ * @param instance root hub instance
+ * @param feature feature selector
+ * @return error code
+ */
+static int process_hub_feature_clear_request(rh_t *instance,
+    uint16_t feature) {
+	if (!((1 << feature) & hub_clear_feature_valid_mask))
+		return EINVAL;
+	//is the feature cleared directly?
+	if ((1 << feature) & hub_set_feature_direct_mask) {
+		instance->registers->rh_status =
+		    (instance->registers->rh_status & (~(1 << feature)))
+		    & (~hub_clear_feature_by_writing_one_mask);
+	} else {//the feature is cleared by writing '1'
+
+		instance->registers->rh_status =
+		    (instance->registers->rh_status
+		    & (~hub_clear_feature_by_writing_one_mask))
+		    | (1 << feature);
+	}
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process feature-enabling request on hub
+ *
+ * @param instance root hub instance
+ * @param feature feature selector
+ * @param port port number, counted from 1
+ * @param enable enable or disable the specified feature
+ * @return error code
+ */
+static int process_port_feature_set_request(rh_t *instance,
+    uint16_t feature, uint16_t port) {
+	if (!((1 << feature) & port_set_feature_valid_mask))
+		return EINVAL;
+	if (port < 1 || port > instance->port_count)
+		return EINVAL;
+	instance->registers->rh_port_status[port - 1] =
+	    (instance->registers->rh_port_status[port - 1] | (1 << feature))
+	    & (~port_clear_feature_valid_mask);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process feature-disabling request on hub
+ *
+ * @param instance root hub instance
+ * @param feature feature selector
+ * @param port port number, counted from 1
+ * @param enable enable or disable the specified feature
+ * @return error code
+ */
+static int process_port_feature_clear_request(rh_t *instance,
+    uint16_t feature, uint16_t port) {
+	if (!((1 << feature) & port_clear_feature_valid_mask))
+		return EINVAL;
+	if (port < 1 || port > instance->port_count)
+		return EINVAL;
+	if (feature == USB_HUB_FEATURE_PORT_POWER)
+		feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
+	if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
+		feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
+	instance->registers->rh_port_status[port - 1] =
+	    (instance->registers->rh_port_status[port - 1]
+	    & (~port_clear_feature_valid_mask))
+	    | (1 << feature);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * register address to this device
+ *
+ * @param instance root hub instance
+ * @param address new address
+ * @return error code
+ */
+static int process_address_set_request(rh_t *instance,
+    uint16_t address) {
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process one of requests that requere output data
+ *
+ * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or
+ * USB_DEVREQ_GET_CONFIGURATION.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_request_with_output(rh_t *instance,
+    usb_transfer_batch_t *request) {
+	usb_device_request_setup_packet_t * setup_request =
+	    (usb_device_request_setup_packet_t*) request->setup_buffer;
+	if (setup_request->request == USB_DEVREQ_GET_STATUS) {
+		usb_log_debug("USB_DEVREQ_GET_STATUS\n");
+		return process_get_status_request(instance, request);
+	}
+	if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
+		usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
+		return process_get_descriptor_request(instance, request);
+	}
+	if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
+		usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
+
+		return process_get_configuration_request(instance, request);
+	}
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process one of requests that carry input data
+ *
+ * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or
+ * USB_DEVREQ_SET_CONFIGURATION.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_request_with_input(rh_t *instance,
+    usb_transfer_batch_t *request) {
+	usb_device_request_setup_packet_t * setup_request =
+	    (usb_device_request_setup_packet_t*) request->setup_buffer;
+	request->transfered_size = 0;
+	if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
+		return ENOTSUP;
+	}
+	if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
+		//set and get configuration requests do not have any meaning,
+		//only dummy values are returned
+
+		return EOK;
+	}
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process one of requests that do not request nor carry additional data
+ *
+ * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or
+ * USB_DEVREQ_SET_ADDRESS.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_request_without_data(rh_t *instance,
+    usb_transfer_batch_t *request) {
+	usb_device_request_setup_packet_t * setup_request =
+	    (usb_device_request_setup_packet_t*) request->setup_buffer;
+	request->transfered_size = 0;
+	if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
+		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
+			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
+			return process_hub_feature_clear_request(instance,
+			    setup_request->value);
+		}
+		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
+			usb_log_debug2("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
+			return process_port_feature_clear_request(instance,
+			    setup_request->value,
+			    setup_request->index);
+		}
+		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
+		    setup_request->request_type);
+		return EINVAL;
+	}
+	if (setup_request->request == USB_DEVREQ_SET_FEATURE) {
+		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
+			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
+			return process_hub_feature_set_request(instance,
+			    setup_request->value);
+		}
+		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
+			usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
+			return process_port_feature_set_request(instance,
+			    setup_request->value,
+			    setup_request->index);
+		}
+		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
+		    setup_request->request_type);
+		return EINVAL;
+	}
+	if (setup_request->request == USB_DEVREQ_SET_ADDRESS) {
+		usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
+		return process_address_set_request(instance,
+		    setup_request->value);
+	}
+	usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
+	    setup_request->request_type);
+
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process hub control request
+ *
+ * If needed, writes answer into the request structure.
+ * Request can be one of
+ * USB_DEVREQ_GET_STATUS,
+ * USB_DEVREQ_GET_DESCRIPTOR,
+ * USB_DEVREQ_GET_CONFIGURATION,
+ * USB_DEVREQ_CLEAR_FEATURE,
+ * USB_DEVREQ_SET_FEATURE,
+ * USB_DEVREQ_SET_ADDRESS,
+ * USB_DEVREQ_SET_DESCRIPTOR or
+ * USB_DEVREQ_SET_CONFIGURATION.
+ *
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
+	if (!request->setup_buffer) {
+		usb_log_error("root hub received empty transaction?");
+		return EINVAL;
+	}
+	int opResult;
+	if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
+		usb_log_error("Setup packet too small\n");
+		return EINVAL;
+	}
+	usb_log_debug("CTRL packet: %s.\n",
+	    usb_debug_str_buffer(
+	    (const uint8_t *) request->setup_buffer, 8, 8));
+	usb_device_request_setup_packet_t * setup_request =
+	    (usb_device_request_setup_packet_t*)
+	    request->setup_buffer;
+	switch (setup_request->request) {
+		case USB_DEVREQ_GET_STATUS:
+		case USB_DEVREQ_GET_DESCRIPTOR:
+		case USB_DEVREQ_GET_CONFIGURATION:
+			usb_log_debug2("Processing request with output\n");
+			opResult = process_request_with_output(
+			    instance, request);
+			break;
+		case USB_DEVREQ_CLEAR_FEATURE:
+		case USB_DEVREQ_SET_FEATURE:
+		case USB_DEVREQ_SET_ADDRESS:
+			usb_log_debug2("Processing request without "
+			    "additional data\n");
+			opResult = process_request_without_data(
+			    instance, request);
+			break;
+		case USB_DEVREQ_SET_DESCRIPTOR:
+		case USB_DEVREQ_SET_CONFIGURATION:
+			usb_log_debug2("Processing request with input\n");
+			opResult = process_request_with_input(
+			    instance, request);
+
+			break;
+		default:
+			usb_log_warning("Received unsupported request: %d.\n",
+			    setup_request->request);
+			opResult = ENOTSUP;
+	}
+	return opResult;
+}
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process hanging interrupt request
+ *
+ * If an interrupt transfer has been received and there was no change,
+ * the driver stores the transfer information and waits for change to occcur.
+ * This routine is called when that happens and it finalizes the interrupt
+ * transfer.
+ *
+ * @param instance hub instance
+ * @param request batch request to be processed
+ *
+ * @return
+ */
+static int process_interrupt_mask_in_instance(rh_t *instance,
+    usb_transfer_batch_t * request) {
+	memcpy(request->data_buffer, instance->interrupt_buffer,
+	    instance->interrupt_mask_size);
+	request->transfered_size = instance->interrupt_mask_size;
+	instance->unfinished_interrupt_transfer = NULL;
+	usb_transfer_batch_finish_error(request, EOK);
+
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * return whether the buffer is full of zeros
+ *
+ * Convenience function.
+ * @param buffer
+ * @param size
+ * @return
+ */
+static bool is_zeros(void *buffer, size_t size) {
+	if (!buffer) return true;
+	if (!size) return true;
+	size_t i;
+	for (i = 0; i < size; ++i) {
+		if (((char*) buffer)[i])
+			return false;
+	}
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/root_hub.h
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/root_hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_ROOT_HUB_H
+#define DRV_OHCI_ROOT_HUB_H
+
+#include <usb/usb.h>
+#include <usb/dev/driver.h>
+
+#include "ohci_regs.h"
+#include "batch.h"
+
+/**
+ * ohci root hub representation
+ */
+typedef struct rh {
+	/** pointer to ohci driver registers */
+	ohci_regs_t *registers;
+	/** usb address of the root hub */
+	usb_address_t address;
+	/** hub port count */
+	size_t port_count;
+	/** hubs descriptors */
+	usb_device_descriptors_t descriptors;
+	/** interrupt transfer waiting for an actual interrupt to occur */
+	usb_transfer_batch_t * unfinished_interrupt_transfer;
+	/** pre-allocated interrupt mask
+	 *
+	 * This is allocated when initializing instance, so that memory
+	 * allocation is not needed when processing request. Buffer is used for
+	 * interrupt bitmask.
+	 */
+	uint8_t * interrupt_buffer;
+	/** size of interrupt buffer */
+	size_t interrupt_mask_size;
+	/** instance`s descriptor*/
+	uint8_t * hub_descriptor;
+	/** size of hub descriptor */
+	size_t descriptor_size;
+
+
+} rh_t;
+
+int rh_init(rh_t *instance, ohci_regs_t *regs);
+
+int rh_request(rh_t *instance, usb_transfer_batch_t *request);
+
+void rh_interrupt(rh_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/ohci/utils/malloc32.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/ohci/utils/malloc32.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,75 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_UTILS_MALLOC32_H
+#define DRV_OHCI_UTILS_MALLOC32_H
+
+#include <assert.h>
+#include <malloc.h>
+#include <errno.h>
+#include <mem.h>
+#include <as.h>
+
+/** Get physical address translation
+ *
+ * @param[in] addr Virtual address to translate
+ * @return Physical address if exists, NULL otherwise.
+ */
+static inline uintptr_t addr_to_phys(void *addr)
+{
+	uintptr_t result;
+	int ret = as_get_physical_mapping(addr, &result);
+
+	if (ret != EOK)
+		return 0;
+	return (result | ((uintptr_t)addr & 0xfff));
+}
+/*----------------------------------------------------------------------------*/
+/** Physical mallocator simulator
+ *
+ * @param[in] size Size of the required memory space
+ * @return Address of the aligned and big enough memory place, NULL on failure.
+ */
+static inline void * malloc32(size_t size)
+	{ return memalign(size, size); }
+/*----------------------------------------------------------------------------*/
+/** Physical mallocator simulator
+ *
+ * @param[in] addr Address of the place allocated by malloc32
+ */
+static inline void free32(void *addr)
+	{ if (addr) free(addr); }
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/Makefile
===================================================================
--- uspace/drv/bus/usb/uhci/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,54 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = uhci
+
+SOURCES = \
+	iface.c \
+	main.c \
+	transfer_list.c \
+	uhci.c \
+	hc.c \
+	root_hub.c \
+	hw_struct/transfer_descriptor.c \
+	pci.c \
+	batch.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/uhci/batch.c
===================================================================
--- uspace/drv/bus/usb/uhci/batch.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/batch.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver USB transfer structure
+ */
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/usb.h>
+#include <usb/debug.h>
+
+#include "batch.h"
+#include "transfer_list.h"
+#include "hw_struct/transfer_descriptor.h"
+#include "utils/malloc32.h"
+
+#define DEFAULT_ERROR_COUNT 3
+
+/** UHCI specific data required for USB transfer */
+typedef struct uhci_transfer_batch {
+	/** Queue head
+	 * This QH is used to maintain UHCI schedule structure and the element
+	 * pointer points to the first TD of this batch.
+	 */
+	qh_t *qh;
+	/** List of TDs needed for the transfer */
+	td_t *tds;
+	/** Number of TDs used by the transfer */
+	size_t td_count;
+	/** Data buffer, must be accessible by the UHCI hw */
+	void *device_buffer;
+} uhci_transfer_batch_t;
+/*----------------------------------------------------------------------------*/
+static void batch_control(usb_transfer_batch_t *instance,
+    usb_packet_id data_stage, usb_packet_id status_stage);
+static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
+/*----------------------------------------------------------------------------*/
+/** Safely destructs uhci_transfer_batch_t structure
+ *
+ * @param[in] uhci_batch Instance to destroy.
+ */
+static void uhci_transfer_batch_dispose(void *uhci_batch)
+{
+	uhci_transfer_batch_t *instance = uhci_batch;
+	assert(instance);
+	free32(instance->device_buffer);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Allocate memory and initialize internal data structure.
+ *
+ * @param[in] fun DDF function to pass to callback.
+ * @param[in] ep Communication target
+ * @param[in] buffer Data source/destination.
+ * @param[in] buffer_size Size of the buffer.
+ * @param[in] setup_buffer Setup data source (if not NULL)
+ * @param[in] setup_size Size of setup_buffer (should be always 8)
+ * @param[in] func_in function to call on inbound transfer completion
+ * @param[in] func_out function to call on outbound transfer completion
+ * @param[in] arg additional parameter to func_in or func_out
+ * @return Valid pointer if all structures were successfully created,
+ * NULL otherwise.
+ *
+ * Determines the number of needed transfer descriptors (TDs).
+ * Prepares a transport buffer (that is accessible by the hardware).
+ * Initializes parameters needed for the transfer and callback.
+ */
+usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
+    char *buffer, size_t buffer_size,
+    const 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(ep);
+	assert(func_in == NULL || func_out == NULL);
+	assert(func_in != NULL || func_out != NULL);
+
+#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
+	if (ptr == NULL) { \
+		usb_log_error(message); \
+		if (uhci_data) { \
+			uhci_transfer_batch_dispose(uhci_data); \
+		} \
+		return NULL; \
+	} else (void)0
+
+	uhci_transfer_batch_t *uhci_data =
+	    malloc(sizeof(uhci_transfer_batch_t));
+	CHECK_NULL_DISPOSE_RETURN(uhci_data,
+	    "Failed to allocate UHCI batch.\n");
+	bzero(uhci_data, sizeof(uhci_transfer_batch_t));
+
+	uhci_data->td_count =
+	    (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
+	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
+		uhci_data->td_count += 2;
+	}
+
+	assert((sizeof(td_t) % 16) == 0);
+	const size_t total_size = (sizeof(td_t) * uhci_data->td_count)
+	    + sizeof(qh_t) + setup_size + buffer_size;
+	uhci_data->device_buffer = malloc32(total_size);
+	CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer,
+	    "Failed to allocate UHCI buffer.\n");
+	bzero(uhci_data->device_buffer, total_size);
+
+	uhci_data->tds = uhci_data->device_buffer;
+	uhci_data->qh =
+	    (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count));
+
+	qh_init(uhci_data->qh);
+	qh_set_element_td(uhci_data->qh, uhci_data->tds);
+
+	usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
+	CHECK_NULL_DISPOSE_RETURN(instance,
+	    "Failed to allocate batch instance.\n");
+	void *setup =
+	    uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)
+	    + sizeof(qh_t);
+	void *data_buffer = setup + setup_size;
+	usb_transfer_batch_init(instance, ep, buffer, data_buffer, buffer_size,
+	    setup, setup_size, func_in, func_out, arg, fun,
+	    uhci_data, uhci_transfer_batch_dispose);
+
+	memcpy(instance->setup_buffer, setup_buffer, setup_size);
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
+	    " memory structures ready.\n", instance,
+	    USB_TRANSFER_BATCH_ARGS(*instance));
+	return instance;
+}
+/*----------------------------------------------------------------------------*/
+/** Check batch TDs for activity.
+ *
+ * @param[in] instance Batch structure to use.
+ * @return False, if there is an active TD, true otherwise.
+ *
+ * Walk all TDs. Stop with false if there is an active one (it is to be
+ * processed). Stop with true if an error is found. Return true if the last TD
+ * is reached.
+ */
+bool batch_is_complete(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	uhci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+
+	usb_log_debug2("Batch(%p) checking %zu transfer(s) for completion.\n",
+	    instance, data->td_count);
+	instance->transfered_size = 0;
+	size_t i = 0;
+	for (;i < data->td_count; ++i) {
+		if (td_is_active(&data->tds[i])) {
+			return false;
+		}
+
+		instance->error = td_status(&data->tds[i]);
+		if (instance->error != EOK) {
+			usb_log_debug("Batch(%p) found error TD(%zu):%"
+			    PRIx32 ".\n", instance, i, data->tds[i].status);
+			td_print_status(&data->tds[i]);
+
+			assert(instance->ep != NULL);
+			endpoint_toggle_set(instance->ep,
+			    td_toggle(&data->tds[i]));
+			if (i > 0)
+				goto substract_ret;
+			return true;
+		}
+
+		instance->transfered_size += td_act_size(&data->tds[i]);
+		if (td_is_short(&data->tds[i]))
+			goto substract_ret;
+	}
+substract_ret:
+	instance->transfered_size -= instance->setup_size;
+	return true;
+}
+
+#define LOG_BATCH_INITIALIZED(batch, name) \
+	usb_log_debug2("Batch %p %s " USB_TRANSFER_BATCH_FMT " initialized.\n", \
+	    (batch), (name), USB_TRANSFER_BATCH_ARGS(*(batch)))
+
+/*----------------------------------------------------------------------------*/
+/** Prepares control write transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control function with pids OUT and IN.
+ */
+void batch_control_write(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	batch_control(instance, USB_PID_OUT, USB_PID_IN);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "control write");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares control read transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control with pids IN and OUT.
+ */
+void batch_control_read(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	batch_control(instance, USB_PID_IN, USB_PID_OUT);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "control read");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare interrupt in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_IN.
+ */
+void batch_interrupt_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	batch_data(instance, USB_PID_IN);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "interrupt in");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare interrupt out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_OUT.
+ */
+void batch_interrupt_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	batch_data(instance, USB_PID_OUT);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "interrupt out");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare bulk in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_IN.
+ */
+void batch_bulk_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	batch_data(instance, USB_PID_IN);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "bulk in");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare bulk out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_OUT.
+ */
+void batch_bulk_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	batch_data(instance, USB_PID_OUT);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "bulk out");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare generic data transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] pid Pid to use for data transactions.
+ *
+ * Transactions with alternating toggle bit and supplied pid value.
+ * The last transfer is marked with IOC flag.
+ */
+void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid)
+{
+	assert(instance);
+	uhci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+
+	const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
+	int toggle = endpoint_toggle_get(instance->ep);
+	assert(toggle == 0 || toggle == 1);
+
+	size_t td = 0;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		const size_t packet_size =
+		    (instance->ep->max_packet_size > remain_size) ?
+		    remain_size : instance->ep->max_packet_size;
+
+		td_t *next_td = (td + 1 < data->td_count)
+		    ? &data->tds[td + 1] : NULL;
+
+
+		usb_target_t target =
+		    { instance->ep->address, instance->ep->endpoint };
+
+		assert(td < data->td_count);
+		td_init(
+		    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, target, pid, buffer, next_td);
+
+		++td;
+		toggle = 1 - toggle;
+		buffer += packet_size;
+		assert(packet_size <= remain_size);
+		remain_size -= packet_size;
+	}
+	td_set_ioc(&data->tds[td - 1]);
+	endpoint_toggle_set(instance->ep, toggle);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare generic control transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] data_stage Pid to use for data tds.
+ * @param[in] status_stage Pid to use for data tds.
+ *
+ * Setup stage with toggle 0 and USB_PID_SETUP.
+ * Data stage with alternating toggle and pid supplied by parameter.
+ * Status stage with toggle 1 and pid supplied by parameter.
+ * The last transfer is marked with IOC.
+ */
+void batch_control(usb_transfer_batch_t *instance,
+   usb_packet_id data_stage, usb_packet_id status_stage)
+{
+	assert(instance);
+	uhci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	assert(data->td_count >= 2);
+
+	const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
+	const usb_target_t target =
+	    { instance->ep->address, instance->ep->endpoint };
+
+	/* setup stage */
+	td_init(
+	    data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
+	    low_speed, target, USB_PID_SETUP, instance->setup_buffer,
+	    &data->tds[1]);
+
+	/* data stage */
+	size_t td = 1;
+	unsigned toggle = 1;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		const size_t packet_size =
+		    (instance->ep->max_packet_size > remain_size) ?
+		    remain_size : instance->ep->max_packet_size;
+
+		td_init(
+		    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, target, data_stage,
+		    buffer, &data->tds[td + 1]);
+
+		++td;
+		toggle = 1 - toggle;
+		buffer += packet_size;
+		assert(td < data->td_count);
+		assert(packet_size <= remain_size);
+		remain_size -= packet_size;
+	}
+
+	/* status stage */
+	assert(td == data->td_count - 1);
+
+	td_init(
+	    &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
+	    target, status_stage, NULL, NULL);
+	td_set_ioc(&data->tds[td]);
+
+	usb_log_debug2("Control last TD status: %x.\n",
+	    data->tds[td].status);
+}
+/*----------------------------------------------------------------------------*/
+/** Provides access to QH data structure.
+ *
+ * @param[in] instance Batch pointer to use.
+ * @return Pointer to the QH used by the batch.
+ */
+qh_t * batch_qh(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	uhci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	return data->qh;
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/batch.h
===================================================================
--- uspace/drv/bus/usb/uhci/batch.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/batch.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver USB tranfer helper functions
+ */
+#ifndef DRV_UHCI_BATCH_H
+#define DRV_UHCI_BATCH_H
+
+#include <usb/host/batch.h>
+
+#include "hw_struct/queue_head.h"
+
+usb_transfer_batch_t * batch_get(
+    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
+    const 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);
+
+void batch_dispose(usb_transfer_batch_t *instance);
+
+bool batch_is_complete(usb_transfer_batch_t *instance);
+
+void batch_control_write(usb_transfer_batch_t *instance);
+void batch_control_read(usb_transfer_batch_t *instance);
+
+void batch_interrupt_in(usb_transfer_batch_t *instance);
+void batch_interrupt_out(usb_transfer_batch_t *instance);
+
+void batch_bulk_in(usb_transfer_batch_t *instance);
+void batch_bulk_out(usb_transfer_batch_t *instance);
+
+qh_t * batch_qh(usb_transfer_batch_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI Host controller driver routines
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <adt/list.h>
+#include <libarch/ddi.h>
+
+#include <usb/debug.h>
+#include <usb/usb.h>
+
+#include "hc.h"
+
+#define UHCI_INTR_ALLOW_INTERRUPTS \
+    (UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET)
+#define UHCI_STATUS_USED_INTERRUPTS \
+    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
+
+
+static int hc_init_transfer_lists(hc_t *instance);
+static int hc_init_mem_structures(hc_t *instance);
+static void hc_init_hw(hc_t *instance);
+
+static int hc_interrupt_emulator(void *arg);
+static int hc_debug_checker(void *arg);
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc driver structure
+ *
+ * @param[in] instance Memory place to initialize.
+ * @param[in] regs Address of I/O control registers.
+ * @param[in] reg_size Size of I/O control registers.
+ * @param[in] interrupts True if hw interrupts should be used.
+ * @return Error code.
+ * @note Should be called only once on any structure.
+ *
+ * Initializes memory structures, starts up hw, and launches debugger and
+ * interrupt fibrils.
+ */
+int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
+{
+	assert(reg_size >= sizeof(regs_t));
+	int ret;
+
+#define CHECK_RET_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		return ret; \
+	} else (void) 0
+
+	instance->hw_interrupts = interrupts;
+	instance->hw_failures = 0;
+
+	/* allow access to hc control registers */
+	regs_t *io;
+	ret = pio_enable(regs, reg_size, (void **)&io);
+	CHECK_RET_RETURN(ret,
+	    "Failed(%d) to gain access to registers at %p: %s.\n",
+	    ret, io, str_error(ret));
+	instance->registers = io;
+	usb_log_debug("Device registers at %p (%zuB) accessible.\n",
+	    io, reg_size);
+
+	ret = hc_init_mem_structures(instance);
+	CHECK_RET_RETURN(ret,
+	    "Failed(%d) to initialize UHCI memory structures: %s.\n",
+	    ret, str_error(ret));
+
+	hc_init_hw(instance);
+	if (!interrupts) {
+		instance->interrupt_emulator =
+		    fibril_create(hc_interrupt_emulator, instance);
+		fibril_add_ready(instance->interrupt_emulator);
+	}
+	(void)hc_debug_checker;
+
+	return EOK;
+#undef CHECK_RET_DEST_FUN_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc hw resources.
+ *
+ * @param[in] instance UHCI structure to use.
+ * For magic values see UHCI Design Guide
+ */
+void hc_init_hw(hc_t *instance)
+{
+	assert(instance);
+	regs_t *registers = instance->registers;
+
+	/* Reset everything, who knows what touched it before us */
+	pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
+	async_usleep(10000); /* 10ms according to USB spec */
+	pio_write_16(&registers->usbcmd, 0);
+
+	/* Reset hc, all states and counters */
+	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
+	do { async_usleep(10); }
+	while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
+
+	/* Set frame to exactly 1ms */
+	pio_write_8(&registers->sofmod, 64);
+
+	/* Set frame list pointer */
+	const uint32_t pa = addr_to_phys(instance->frame_list);
+	pio_write_32(&registers->flbaseadd, pa);
+
+	if (instance->hw_interrupts) {
+		/* Enable all interrupts, but resume interrupt */
+		pio_write_16(&instance->registers->usbintr,
+		    UHCI_INTR_ALLOW_INTERRUPTS);
+	}
+
+	const uint16_t status = pio_read_16(&registers->usbcmd);
+	if (status != 0)
+		usb_log_warning("Previous command value: %x.\n", status);
+
+	/* Start the hc with large(64B) packet FSBR */
+	pio_write_16(&registers->usbcmd,
+	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc memory structures.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @return Error code
+ * @note Should be called only once on any structure.
+ *
+ * Structures:
+ *  - interrupt code (I/O addressses are customized per instance)
+ *  - transfer lists (queue heads need to be accessible by the hw)
+ *  - frame list page (needs to be one UHCI hw accessible 4K page)
+ */
+int hc_init_mem_structures(hc_t *instance)
+{
+	assert(instance);
+#define CHECK_RET_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		return ret; \
+	} else (void) 0
+
+	/* Init interrupt code */
+	instance->interrupt_code.cmds = instance->interrupt_commands;
+	{
+		/* Read status register */
+		instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;
+		instance->interrupt_commands[0].dstarg = 1;
+		instance->interrupt_commands[0].addr =
+		    &instance->registers->usbsts;
+
+		/* Test whether we are the interrupt cause */
+		instance->interrupt_commands[1].cmd = CMD_BTEST;
+		instance->interrupt_commands[1].value =
+		    UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;
+		instance->interrupt_commands[1].srcarg = 1;
+		instance->interrupt_commands[1].dstarg = 2;
+
+		/* Predicate cleaning and accepting */
+		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
+		instance->interrupt_commands[2].value = 2;
+		instance->interrupt_commands[2].srcarg = 2;
+
+		/* Write clean status register */
+		instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;
+		instance->interrupt_commands[3].srcarg = 1;
+		instance->interrupt_commands[3].addr =
+		    &instance->registers->usbsts;
+
+		/* Accept interrupt */
+		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
+
+		instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;
+	}
+
+	/* Init transfer lists */
+	int ret = hc_init_transfer_lists(instance);
+	CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
+	usb_log_debug("Initialized transfer lists.\n");
+
+	/* Init USB frame list page*/
+	instance->frame_list = get_page();
+	ret = instance->frame_list ? EOK : ENOMEM;
+	CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
+	usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
+
+	/* Set all frames to point to the first queue head */
+	const uint32_t queue = LINK_POINTER_QH(
+	        addr_to_phys(instance->transfers_interrupt.queue_head));
+
+	unsigned i = 0;
+	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
+		instance->frame_list[i] = queue;
+	}
+
+	/* Init device keeper */
+	usb_device_keeper_init(&instance->manager);
+	usb_log_debug("Initialized device manager.\n");
+
+	ret = usb_endpoint_manager_init(&instance->ep_manager,
+	    BANDWIDTH_AVAILABLE_USB11);
+	CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
+	    str_error(ret));
+
+	return EOK;
+#undef CHECK_RET_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc transfer lists.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @return Error code
+ * @note Should be called only once on any structure.
+ *
+ * Initializes transfer lists and sets them in one chain to support proper
+ * USB scheduling. Sets pointer table for quick access.
+ */
+int hc_init_transfer_lists(hc_t *instance)
+{
+	assert(instance);
+#define SETUP_TRANSFER_LIST(type, name) \
+do { \
+	int ret = transfer_list_init(&instance->transfers_##type, name); \
+	if (ret != EOK) { \
+		usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
+		    ret, name, str_error(ret)); \
+		transfer_list_fini(&instance->transfers_bulk_full); \
+		transfer_list_fini(&instance->transfers_control_full); \
+		transfer_list_fini(&instance->transfers_control_slow); \
+		transfer_list_fini(&instance->transfers_interrupt); \
+		return ret; \
+	} \
+} while (0)
+
+	SETUP_TRANSFER_LIST(bulk_full, "BULK FULL");
+	SETUP_TRANSFER_LIST(control_full, "CONTROL FULL");
+	SETUP_TRANSFER_LIST(control_slow, "CONTROL LOW");
+	SETUP_TRANSFER_LIST(interrupt, "INTERRUPT");
+#undef SETUP_TRANSFER_LIST
+	/* Connect lists into one schedule */
+	transfer_list_set_next(&instance->transfers_control_full,
+		&instance->transfers_bulk_full);
+	transfer_list_set_next(&instance->transfers_control_slow,
+		&instance->transfers_control_full);
+	transfer_list_set_next(&instance->transfers_interrupt,
+		&instance->transfers_control_slow);
+
+	/*FSBR, This feature is not needed (adds no benefit) and is supposedly
+	 * buggy on certain hw, enable at your own risk. */
+#ifdef FSBR
+	transfer_list_set_next(&instance->transfers_bulk_full,
+	    &instance->transfers_control_full);
+#endif
+
+	/* Assign pointers to be used during scheduling */
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_full;
+	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_slow;
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
+	  &instance->transfers_bulk_full;
+
+	return EOK;
+#undef CHECK_RET_CLEAR_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule batch for execution.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] batch Transfer batch to schedule.
+ * @return Error code
+ *
+ * Checks for bandwidth availability and appends the batch to the proper queue.
+ */
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+
+	transfer_list_t *list =
+	    instance->transfers[batch->ep->speed][batch->ep->transfer_type];
+	assert(list);
+	transfer_list_add_batch(list, batch);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Take action based on the interrupt cause.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] status Value of the status register at the time of interrupt.
+ *
+ * Interrupt might indicate:
+ * - transaction completed, either by triggering IOC, SPD, or an error
+ * - some kind of device error
+ * - resume from suspend state (not implemented)
+ */
+void hc_interrupt(hc_t *instance, uint16_t status)
+{
+	assert(instance);
+	/* Lower 2 bits are transaction error and transaction complete */
+	if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
+		LIST_INITIALIZE(done);
+		transfer_list_remove_finished(
+		    &instance->transfers_interrupt, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_control_slow, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_control_full, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_bulk_full, &done);
+
+		while (!list_empty(&done)) {
+			link_t *item = list_first(&done);
+			list_remove(item);
+			usb_transfer_batch_t *batch =
+			    list_get_instance(item, usb_transfer_batch_t, link);
+			usb_transfer_batch_finish(batch);
+		}
+	}
+	/* Resume interrupts are not supported */
+	if (status & UHCI_STATUS_RESUME) {
+		usb_log_error("Resume interrupt!\n");
+	}
+
+	/* Bits 4 and 5 indicate hc error */
+	if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
+		usb_log_error("UHCI hardware failure!.\n");
+		++instance->hw_failures;
+		transfer_list_abort_all(&instance->transfers_interrupt);
+		transfer_list_abort_all(&instance->transfers_control_slow);
+		transfer_list_abort_all(&instance->transfers_control_full);
+		transfer_list_abort_all(&instance->transfers_bulk_full);
+
+		if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
+			/* reinitialize hw, this triggers virtual disconnect*/
+			hc_init_hw(instance);
+		} else {
+			usb_log_fatal("Too many UHCI hardware failures!.\n");
+			hc_fini(instance);
+		}
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Polling function, emulates interrupts.
+ *
+ * @param[in] arg UHCI hc structure to use.
+ * @return EOK (should never return)
+ */
+int hc_interrupt_emulator(void* arg)
+{
+	usb_log_debug("Started interrupt emulator.\n");
+	hc_t *instance = arg;
+	assert(instance);
+
+	while (1) {
+		/* Read and clear status register */
+		uint16_t status = pio_read_16(&instance->registers->usbsts);
+		pio_write_16(&instance->registers->usbsts, status);
+		if (status != 0)
+			usb_log_debug2("UHCI status: %x.\n", status);
+// Qemu fails to report stalled communication
+// see https://bugs.launchpad.net/qemu/+bug/757654
+// This is a simple workaround to force queue processing every time
+	//	status |= 1;
+		hc_interrupt(instance, status);
+		async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
+	}
+	return EOK;
+}
+/*---------------------------------------------------------------------------*/
+/** Debug function, checks consistency of memory structures.
+ *
+ * @param[in] arg UHCI structure to use.
+ * @return EOK (should never return)
+ */
+int hc_debug_checker(void *arg)
+{
+	hc_t *instance = arg;
+	assert(instance);
+
+#define QH(queue) \
+	instance->transfers_##queue.queue_head
+
+	while (1) {
+		const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
+		const uint16_t sts = pio_read_16(&instance->registers->usbsts);
+		const uint16_t intr =
+		    pio_read_16(&instance->registers->usbintr);
+
+		if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
+			usb_log_debug2("Command: %X Status: %X Intr: %x\n",
+			    cmd, sts, intr);
+		}
+
+		const uintptr_t frame_list =
+		    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
+		if (frame_list != addr_to_phys(instance->frame_list)) {
+			usb_log_debug("Framelist address: %p vs. %p.\n",
+			    (void *) frame_list,
+			    (void *) addr_to_phys(instance->frame_list));
+		}
+
+		int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
+
+		uintptr_t expected_pa = instance->frame_list[frnum]
+		    & LINK_POINTER_ADDRESS_MASK;
+		uintptr_t real_pa = addr_to_phys(QH(interrupt));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Interrupt QH: %p (frame %d) vs. %p.\n",
+			    (void *) expected_pa, frnum, (void *) real_pa);
+		}
+
+		expected_pa = QH(interrupt)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(control_slow));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Control Slow QH: %p vs. %p.\n",
+			    (void *) expected_pa, (void *) real_pa);
+		}
+
+		expected_pa = QH(control_slow)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(control_full));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Control Full QH: %p vs. %p.\n",
+			    (void *) expected_pa, (void *) real_pa);
+		}
+
+		expected_pa = QH(control_full)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(bulk_full));
+		if (expected_pa != real_pa ) {
+			usb_log_debug("Bulk QH: %p vs. %p.\n",
+			    (void *) expected_pa, (void *) real_pa);
+		}
+		async_usleep(UHCI_DEBUGER_TIMEOUT);
+	}
+	return EOK;
+#undef QH
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI host controller driver structure
+ */
+#ifndef DRV_UHCI_HC_H
+#define DRV_UHCI_HC_H
+
+#include <fibril.h>
+#include <ddi.h>
+
+#include <usb/host/device_keeper.h>
+#include <usb/host/usb_endpoint_manager.h>
+#include <usb/host/batch.h>
+
+#include "transfer_list.h"
+
+/** UHCI I/O registers layout */
+typedef struct uhci_regs {
+	/** Command register, controls HC behaviour */
+	uint16_t usbcmd;
+#define UHCI_CMD_MAX_PACKET (1 << 7)
+#define UHCI_CMD_CONFIGURE  (1 << 6)
+#define UHCI_CMD_DEBUG  (1 << 5)
+#define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
+#define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
+#define UHCI_CMD_GLOBAL_RESET  (1 << 2)
+#define UHCI_CMD_HCRESET  (1 << 1)
+#define UHCI_CMD_RUN_STOP  (1 << 0)
+
+	/** Status register, 1 means interrupt is asserted (if enabled) */
+	uint16_t usbsts;
+#define UHCI_STATUS_HALTED (1 << 5)
+#define UHCI_STATUS_PROCESS_ERROR (1 << 4)
+#define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
+#define UHCI_STATUS_RESUME (1 << 2)
+#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
+#define UHCI_STATUS_INTERRUPT (1 << 0)
+#define UHCI_STATUS_NM_INTERRUPTS \
+    (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)
+
+	/** Interrupt enabled registers */
+	uint16_t usbintr;
+#define UHCI_INTR_SHORT_PACKET (1 << 3)
+#define UHCI_INTR_COMPLETE (1 << 2)
+#define UHCI_INTR_RESUME (1 << 1)
+#define UHCI_INTR_CRC (1 << 0)
+
+	/** Register stores frame number used in SOF packet */
+	uint16_t frnum;
+
+	/** Pointer(physical) to the Frame List */
+	uint32_t flbaseadd;
+
+	/** SOF modification to match external timers */
+	uint8_t sofmod;
+} regs_t;
+
+#define UHCI_FRAME_LIST_COUNT 1024
+#define UHCI_INT_EMULATOR_TIMEOUT 10000
+#define UHCI_DEBUGER_TIMEOUT 5000000
+#define UHCI_ALLOWED_HW_FAIL 5
+#define UHCI_NEEDED_IRQ_COMMANDS 5
+
+/** Main UHCI driver structure */
+typedef struct hc {
+	/** USB bus driver, devices and addresses */
+	usb_device_keeper_t manager;
+	/** USB bus driver, endpoints */
+	usb_endpoint_manager_t ep_manager;
+
+	/** Addresses of I/O registers */
+	regs_t *registers;
+
+	/** Frame List contains 1024 link pointers */
+	link_pointer_t *frame_list;
+
+	/** List and queue of interrupt transfers */
+	transfer_list_t transfers_interrupt;
+	/** List and queue of low speed control transfers */
+	transfer_list_t transfers_control_slow;
+	/** List and queue of full speed bulk transfers */
+	transfer_list_t transfers_bulk_full;
+	/** List and queue of full speed control transfers */
+	transfer_list_t transfers_control_full;
+
+	/** Pointer table to the above lists, helps during scheduling */
+	transfer_list_t *transfers[2][4];
+
+	/** Code to be executed in kernel interrupt handler */
+	irq_code_t interrupt_code;
+
+	/** Commands that form interrupt code */
+	irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS];
+
+	/** Fibril periodically checking status register*/
+	fid_t interrupt_emulator;
+
+	/** Indicator of hw interrupts availability */
+	bool hw_interrupts;
+
+	/** Number of hw failures detected. */
+	unsigned hw_failures;
+} hc_t;
+
+int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
+
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
+
+void hc_interrupt(hc_t *instance, uint16_t status);
+
+/** Safely dispose host controller internal structures
+ *
+ * @param[in] instance Host controller structure to use.
+ */
+static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
+
+/** Get and cast pointer to the driver data
+ *
+ * @param[in] fun DDF function pointer
+ * @return cast pointer to driver_data
+ */
+static inline hc_t * fun_to_hc(ddf_fun_t *fun)
+{
+	assert(fun);
+	return fun->driver_data;
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,61 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_HW_STRUCT_LINK_POINTER_H
+#define DRV_UHCI_HW_STRUCT_LINK_POINTER_H
+
+/* UHCI link pointer, used by many data structures */
+typedef uint32_t link_pointer_t;
+
+#define LINK_POINTER_TERMINATE_FLAG (1 << 0)
+#define LINK_POINTER_QUEUE_HEAD_FLAG (1 << 1)
+#define LINK_POINTER_ZERO_BIT_FLAG (1 << 2)
+#define LINK_POINTER_VERTICAL_FLAG (1 << 2)
+#define LINK_POINTER_RESERVED_FLAG (1 << 3)
+
+#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
+
+#define LINK_POINTER_QH(address) \
+	((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG)
+
+#define LINK_POINTER_TD(address) \
+	(address & LINK_POINTER_ADDRESS_MASK)
+
+#define LINK_POINTER_TERM \
+	((link_pointer_t)LINK_POINTER_TERMINATE_FLAG)
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/uhci/hw_struct/queue_head.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/queue_head.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/hw_struct/queue_head.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,100 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_HW_STRUCT_QH_H
+#define DRV_UHCI_HW_STRUCT_QH_H
+#include <assert.h>
+
+#include "link_pointer.h"
+#include "transfer_descriptor.h"
+#include "../utils/malloc32.h"
+
+/** This structure is defined in UHCI design guide p. 31 */
+typedef struct queue_head {
+	/** Pointer to the next entity (another QH or TD */
+	volatile link_pointer_t next;
+	/** Pointer to the contained entities (execution controlled by vertical flag*/
+	volatile link_pointer_t element;
+} __attribute__((packed)) qh_t;
+/*----------------------------------------------------------------------------*/
+/** Initialize queue head structure
+ *
+ * @param[in] instance qh_t structure to initialize.
+ *
+ * Sets both pointer to terminal NULL.
+ */
+static inline void qh_init(qh_t *instance)
+{
+	assert(instance);
+
+	instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
+	instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
+}
+/*----------------------------------------------------------------------------*/
+/** Set queue head next pointer
+ *
+ * @param[in] instance qh_t structure to use.
+ * @param[in] next Address of the next queue.
+ *
+ * Adds proper flag. If the pointer is NULL, sets next to terminal NULL.
+ */
+static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
+{
+	uint32_t pa = addr_to_phys(next);
+	if (pa) {
+		instance->next = LINK_POINTER_QH(pa);
+	} else {
+		instance->next = LINK_POINTER_TERM;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Set queue head element pointer
+ *
+ * @param[in] instance qh_t structure to use.
+ * @param[in] td Transfer descriptor to set as the first element.
+ *
+ * Adds proper flag. If the pointer is NULL, sets element to terminal NULL.
+ */
+static inline void qh_set_element_td(qh_t *instance, td_t *td)
+{
+	uint32_t pa = addr_to_phys(td);
+	if (pa) {
+		instance->element = LINK_POINTER_TD(pa);
+	} else {
+		instance->element = LINK_POINTER_TERM;
+	}
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <usb/debug.h>
+
+#include "transfer_descriptor.h"
+#include "../utils/malloc32.h"
+
+/** Initialize Transfer Descriptor
+ *
+ * @param[in] instance Memory place to initialize.
+ * @param[in] err_count Number of retries hc should attempt.
+ * @param[in] size Size of data source.
+ * @param[in] toggle Value of toggle bit.
+ * @param[in] iso True if TD represents Isochronous transfer.
+ * @param[in] low_speed Target device's speed.
+ * @param[in] target Address and endpoint receiving the transfer.
+ * @param[in] pid Packet identification (SETUP, IN or OUT).
+ * @param[in] buffer Source of data.
+ * @param[in] next Net TD in transaction.
+ * @return Error code.
+ *
+ * Uses a mix of supplied and default values.
+ * Implicit values:
+ *  - all TDs have vertical flag set (makes transfers to endpoints atomic)
+ *  - in the error field only active it is set
+ *  - if the packet uses PID_IN and is not isochronous SPD is set
+ *
+ * Dumps 8 bytes of buffer if PID_SETUP is used.
+ */
+void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
+    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
+    td_t *next)
+{
+	assert(instance);
+	assert(size < 1024);
+	assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
+	    || (pid == USB_PID_OUT));
+
+	const uint32_t next_pa = addr_to_phys(next);
+	assert((next_pa & LINK_POINTER_ADDRESS_MASK) == next_pa);
+
+	instance->next = 0
+	    | LINK_POINTER_VERTICAL_FLAG
+	    | (next_pa ? next_pa : LINK_POINTER_TERMINATE_FLAG);
+
+	instance->status = 0
+	    | ((err_count & TD_STATUS_ERROR_COUNT_MASK)
+	        << TD_STATUS_ERROR_COUNT_POS)
+	    | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
+	    | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
+	    | TD_STATUS_ERROR_ACTIVE;
+
+	if (pid == USB_PID_IN && !iso) {
+		instance->status |= TD_STATUS_SPD_FLAG;
+	}
+
+	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)
+	    | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
+
+	instance->buffer_ptr = addr_to_phys(buffer);
+
+	usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
+	    instance, instance->next, instance->status, instance->device,
+	    instance->buffer_ptr, buffer);
+	td_print_status(instance);
+	if (pid == USB_PID_SETUP) {
+		usb_log_debug2("SETUP BUFFER: %s\n",
+		    usb_debug_str_buffer(buffer, 8, 8));
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Convert TD status into standard error code
+ *
+ * @param[in] instance TD structure to use.
+ * @return Error code.
+ */
+int td_status(td_t *instance)
+{
+	assert(instance);
+
+	/* This is hc internal error it should never be reported. */
+	if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
+		return EAGAIN;
+
+	/* CRC or timeout error, like device not present or bad data,
+	 * it won't be reported unless err count reached zero */
+	if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
+		return EBADCHECKSUM;
+
+	/* HC does not end transactions on these, it should never be reported */
+	if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
+		return EAGAIN;
+
+	/* Buffer overrun or underrun */
+	if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
+		return ERANGE;
+
+	/* Device babble is something serious */
+	if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
+		return EIO;
+
+	/* Stall might represent err count reaching zero or stall response from
+	 * the device. If err count reached zero, one of the above is reported*/
+	if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
+		return ESTALL;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Print values in status field (dw1) in a human readable way.
+ *
+ * @param[in] instance TD structure to use.
+ */
+void td_print_status(td_t *instance)
+{
+	assert(instance);
+	const uint32_t s = instance->status;
+	usb_log_debug2("TD(%p) status(%#" PRIx32 "):%s %d,%s%s%s%s%s%s%s%s%s%s%s %zu.\n",
+	    instance, instance->status,
+	    (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
+	    (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK,
+	    (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "",
+	    (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "",
+	    (s & TD_STATUS_IOC_FLAG) ? " IOC," : "",
+	    (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "",
+	    (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "",
+	    (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "",
+	    (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "",
+	    (s & TD_STATUS_ERROR_NAK) ? " NAK," : "",
+	    (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "",
+	    (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
+	    (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
+	    td_act_size(instance)
+	);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
+#define DRV_UHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
+
+#include <mem.h>
+#include <usb/usb.h>
+
+#include "link_pointer.h"
+
+/** Transfer Descriptor, defined in UHCI design guide p. 26 */
+typedef struct transfer_descriptor {
+	/** Pointer to the next entity (TD or QH) */
+	link_pointer_t next;
+
+	/** Status doubleword */
+	volatile uint32_t status;
+#define TD_STATUS_RESERVED_MASK 0xc000f800
+#define TD_STATUS_SPD_FLAG         (1 << 29)
+#define TD_STATUS_ERROR_COUNT_POS 27
+#define TD_STATUS_ERROR_COUNT_MASK 0x3
+#define TD_STATUS_LOW_SPEED_FLAG   (1 << 26)
+#define TD_STATUS_ISOCHRONOUS_FLAG (1 << 25)
+#define TD_STATUS_IOC_FLAG         (1 << 24)
+
+#define TD_STATUS_ERROR_ACTIVE    (1 << 23)
+#define TD_STATUS_ERROR_STALLED   (1 << 22)
+#define TD_STATUS_ERROR_BUFFER    (1 << 21)
+#define TD_STATUS_ERROR_BABBLE    (1 << 20)
+#define TD_STATUS_ERROR_NAK       (1 << 19)
+#define TD_STATUS_ERROR_CRC       (1 << 18)
+#define TD_STATUS_ERROR_BIT_STUFF (1 << 17)
+#define TD_STATUS_ERROR_RESERVED  (1 << 16)
+#define TD_STATUS_ERROR_POS 16
+#define TD_STATUS_ERROR_MASK 0xff
+
+#define TD_STATUS_ACTLEN_POS 0
+#define TD_STATUS_ACTLEN_MASK 0x7ff
+
+	/* double word with USB device specific info */
+	volatile uint32_t device;
+#define TD_DEVICE_MAXLEN_POS 21
+#define TD_DEVICE_MAXLEN_MASK 0x7ff
+#define TD_DEVICE_RESERVED_FLAG        (1 << 20)
+#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG (1 << 19)
+#define TD_DEVICE_ENDPOINT_POS 15
+#define TD_DEVICE_ENDPOINT_MASK 0xf
+#define TD_DEVICE_ADDRESS_POS 8
+#define TD_DEVICE_ADDRESS_MASK 0x7f
+#define TD_DEVICE_PID_POS 0
+#define TD_DEVICE_PID_MASK 0xff
+
+	/** Pointer(physical) to the beginning of the transaction's buffer */
+	volatile uint32_t buffer_ptr;
+
+	/* According to UHCI design guide, there is 16 bytes of
+	 * data available here.
+	 * According to linux kernel the hardware does not care,
+	 * it just needs to be aligned. We don't use it anyway.
+	 */
+} __attribute__((packed)) td_t;
+
+
+void td_init(td_t *instance, int error_count, size_t size, bool toggle,
+    bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
+    void *buffer, td_t *next);
+
+int td_status(td_t *instance);
+
+void td_print_status(td_t *instance);
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing actual size out of TD.
+ *
+ * @param[in] instance TD structure to use.
+ * @return Parsed actual size.
+ */
+static inline size_t td_act_size(td_t *instance)
+{
+	assert(instance);
+	const uint32_t s = instance->status;
+	return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
+}
+/*----------------------------------------------------------------------------*/
+/** Check whether less than max data were received on SPD marked transfer.
+ *
+ * @param[in] instance TD structure to use.
+ * @return True if data packet is short (less than max bytes and SPD set),
+ * false otherwise.
+ */
+static inline bool td_is_short(td_t *instance)
+{
+	const size_t act_size = td_act_size(instance);
+	const size_t max_size =
+	    ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1)
+	    & TD_DEVICE_MAXLEN_MASK;
+	return
+	    (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing value of toggle bit.
+ *
+ * @param[in] instance TD structure to use.
+ * @return Toggle bit value.
+ */
+static inline int td_toggle(td_t *instance)
+{
+	assert(instance);
+	return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing value of active bit
+ *
+ * @param[in] instance TD structure to use.
+ * @return Active bit value.
+ */
+static inline bool td_is_active(td_t *instance)
+{
+	assert(instance);
+	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for setting IOC bit.
+ *
+ * @param[in] instance TD structure to use.
+ */
+static inline void td_set_ioc(td_t *instance)
+{
+	assert(instance);
+	instance->status |= TD_STATUS_IOC_FLAG;
+}
+/*----------------------------------------------------------------------------*/
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/iface.c
===================================================================
--- uspace/drv/bus/usb/uhci/iface.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/iface.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver hc interface implementation
+ */
+#include <ddf/driver.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+#include <usb/host/endpoint.h>
+
+#include "iface.h"
+#include "batch.h"
+#include "hc.h"
+
+static inline int setup_batch(
+    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
+    void *data, size_t size, void * setup_data, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t in,
+    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
+    hc_t **hc, usb_transfer_batch_t **batch)
+{
+	assert(hc);
+	assert(batch);
+	assert(fun);
+	*hc = fun_to_hc(fun);
+	assert(*hc);
+
+	size_t res_bw;
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
+	    target.address, target.endpoint, direction, &res_bw);
+	if (ep == NULL) {
+		usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
+		    target.address, target.endpoint, name);
+		return ENOENT;
+	}
+
+	usb_log_debug2("%s %d:%d %zu(%zu).\n",
+	    name, target.address, target.endpoint, size, ep->max_packet_size);
+
+	const size_t bw = bandwidth_count_usb11(
+	    ep->speed, ep->transfer_type, size, ep->max_packet_size);
+	if (res_bw < bw) {
+		usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
+		    "but only %zu is reserved.\n",
+		    target.address, target.endpoint, name, bw, res_bw);
+		return ENOSPC;
+	}
+
+	*batch = batch_get(
+	        fun, ep, data, size, setup_data, setup_size, in, out, arg);
+	if (!*batch)
+		return ENOMEM;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Request address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] speed Speed to associate with the new default address.
+ * @param[out] address Place to write a new address.
+ * @return Error code.
+ */
+static int request_address(
+    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	assert(address);
+
+	usb_log_debug("Address request with speed %d.\n", speed);
+	*address = device_keeper_get_free_address(&hc->manager, speed);
+	usb_log_debug("Address request with result: %d.\n", *address);
+	if (*address <= 0)
+		return *address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Bind address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address of the device
+ * @param[in] handle Devman handle of the device driver.
+ * @return Error code.
+ */
+static int bind_address(
+  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
+	usb_device_keeper_bind(&hc->manager, address, handle);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	const bool found =
+	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
+	return found ? EOK : ENOENT;
+}
+/*----------------------------------------------------------------------------*/
+/** Release address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address release %d.\n", address);
+	usb_device_keeper_release(&hc->manager, address);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int register_endpoint(
+    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
+    usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	const size_t size = max_packet_size;
+	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
+	if (speed >= USB_SPEED_MAX) {
+		speed = ep_speed;
+	}
+	usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n",
+	    address, endpoint, usb_str_transfer_type(transfer_type),
+	    usb_str_direction(direction), usb_str_speed(speed),
+	    max_packet_size, interval);
+
+	return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
+	    direction, transfer_type, speed, max_packet_size, size);
+}
+/*----------------------------------------------------------------------------*/
+static int unregister_endpoint(
+    ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Unregister endpoint %d:%d %s.\n",
+	    address, endpoint, usb_str_direction(direction));
+	return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
+	    endpoint, direction);
+}
+/*----------------------------------------------------------------------------*/
+/** Interrupt out transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int interrupt_out(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
+	    NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_interrupt_out(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Interrupt in transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[out] data Data destination.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int interrupt_in(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
+	    NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_interrupt_in(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Bulk out transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int bulk_out(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
+	    NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_bulk_out(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Bulk in transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[out] data Data destination.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int bulk_in(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
+	    NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_bulk_in(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Control write transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] setup_data Data to send with SETUP transfer.
+ * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion.
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int control_write(
+    ddf_fun_t *fun, 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)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
+	    setup_data, setup_size, NULL, callback, arg, "Control WRITE",
+	    &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
+	batch_control_write(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Control read transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] setup_data Data to send with SETUP packet.
+ * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
+ * @param[out] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion.
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int control_read(
+    ddf_fun_t *fun, 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)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
+	    setup_data, setup_size, callback, NULL, arg, "Control READ",
+	    &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_control_read(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+usbhc_iface_t hc_iface = {
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.find_by_address = find_by_address,
+	.release_address = release_address,
+
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.bulk_out = bulk_out,
+	.bulk_in = bulk_in,
+
+	.control_write = control_write,
+	.control_read = control_read,
+};
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/iface.h
===================================================================
--- uspace/drv/bus/usb/uhci/iface.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/iface.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,45 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver iface
+ */
+#ifndef DRV_UHCI_IFACE_H
+#define DRV_UHCI_IFACE_H
+
+#include <usbhc_iface.h>
+
+extern usbhc_iface_t hc_iface;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/main.c
===================================================================
--- uspace/drv/bus/usb/uhci/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver initialization
+ */
+#include <ddf/driver.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "uhci.h"
+
+#define NAME "uhci"
+
+static int uhci_add_device(ddf_dev_t *device);
+/*----------------------------------------------------------------------------*/
+static driver_ops_t uhci_driver_ops = {
+	.add_device = uhci_add_device,
+};
+/*----------------------------------------------------------------------------*/
+static driver_t uhci_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_driver_ops
+};
+/*----------------------------------------------------------------------------*/
+/** Initialize a new ddf driver instance for uhci hc and hub.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+int uhci_add_device(ddf_dev_t *device)
+{
+	usb_log_debug2("uhci_add_device() called\n");
+	assert(device);
+
+	int ret = device_setup_uhci(device);
+	if (ret != EOK) {
+		usb_log_error("Failed to initialize UHCI driver: %s.\n",
+		    str_error(ret));
+		return ret;
+	}
+	usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize global driver structures (NONE).
+ *
+ * @param[in] argc Number of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS UHCI driver.\n");
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return ddf_driver_main(&uhci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/pci.c
===================================================================
--- uspace/drv/bus/usb/uhci/pci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/pci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,169 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the UHCI driver.
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include <devman.h>
+#include <device/hw_res.h>
+
+#include <usb/debug.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+/** Get I/O address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the I/O range.
+ * @param[out] io_reg_size Size of the I/O range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(const ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
+{
+	assert(dev);
+	assert(io_reg_address);
+	assert(io_reg_size);
+	assert(irq_no);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	hw_resource_list_t hw_resources;
+	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (rc != EOK) {
+		async_hangup(parent_sess);
+		return rc;
+	}
+	
+	uintptr_t io_address = 0;
+	size_t io_size = 0;
+	bool io_found = false;
+	
+	int irq = 0;
+	bool irq_found = false;
+	
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		const hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			irq = res->res.interrupt.irq;
+			irq_found = true;
+			usb_log_debug2("Found interrupt: %d.\n", irq);
+			break;
+		case IO_RANGE:
+			io_address = res->res.io_range.address;
+			io_size = res->res.io_range.size;
+			usb_log_debug2("Found io: %" PRIx64" %zu.\n",
+			    res->res.io_range.address, res->res.io_range.size);
+			io_found = true;
+			break;
+		default:
+			break;
+		}
+	}
+	
+	async_hangup(parent_sess);
+	
+	if (!io_found || !irq_found)
+		return ENOENT;
+	
+	*io_reg_address = io_address;
+	*io_reg_size = io_size;
+	*irq_no = irq;
+	
+	return EOK;
+}
+
+/** Call the PCI driver with a request to enable interrupts
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_enable_interrupts(const ddf_dev_t *device)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	const bool enabled = hw_res_enable_interrupt(parent_sess);
+	async_hangup(parent_sess);
+	
+	return enabled ? EOK : EIO;
+}
+
+/** Call the PCI driver with a request to clear legacy support register
+ *
+ * @param[in] device Device asking to disable interrupts
+ * @return Error code.
+ */
+int pci_disable_legacy(const ddf_dev_t *device)
+{
+	assert(device);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	/* See UHCI design guide for these values p.45,
+	 * write all WC bits in USB legacy register */
+	const sysarg_t address = 0xc0;
+	const sysarg_t value = 0xaf00;
+	
+	async_exch_t *exch = async_exchange_begin(parent_sess);
+	
+	const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE),
+	    IPC_M_CONFIG_SPACE_WRITE_16, address, value);
+	
+	async_exchange_end(exch);
+	async_hangup(parent_sess);
+	
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/pci.h
===================================================================
--- uspace/drv/bus/usb/uhci/pci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/pci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,48 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver PCI helper functions
+ */
+#ifndef DRV_UHCI_PCI_H
+#define DRV_UHCI_PCI_H
+
+#include <ddf/driver.h>
+
+int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(const ddf_dev_t *);
+int pci_disable_legacy(const ddf_dev_t *);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/uhci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhci/root_hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/root_hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,85 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+/** Root hub initialization
+ * @param[in] instance RH structure to initialize
+ * @param[in] fun DDF function representing UHCI root hub
+ * @param[in] reg_addr Address of root hub status and control registers.
+ * @param[in] reg_size Size of accessible address space.
+ * @return Error code.
+ */
+int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
+{
+	assert(fun);
+
+	char *match_str = NULL;
+	int ret = asprintf(&match_str, "usb&uhci&root-hub");
+	if (ret < 0) {
+		usb_log_error(
+		    "Failed(%d) to create root hub match string: %s.\n",
+		    ret, str_error(ret));
+		return ret;
+	}
+	assert(match_str);
+
+	ret = ddf_fun_add_match_id(fun, match_str, 100);
+	if (ret != EOK) {
+		free(match_str);
+		usb_log_error("Failed(%d) to add root hub match id: %s\n",
+		    ret, str_error(ret));
+		return ret;
+	}
+
+	/* Initialize resource structure */
+	instance->resource_list.count = 1;
+	instance->resource_list.resources = &instance->io_regs;
+
+	instance->io_regs.type = IO_RANGE;
+	instance->io_regs.res.io_range.address = reg_addr;
+	instance->io_regs.res.io_range.size = reg_size;
+	instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
+
+	return EOK;
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/root_hub.h
===================================================================
--- uspace/drv/bus/usb/uhci/root_hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/root_hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,55 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_RH_H
+#define DRV_UHCI_RH_H
+
+#include <ddf/driver.h>
+#include <ops/hw_res.h>
+
+/** DDF support structure for uhci_rhd driver, provides I/O resources */
+typedef struct rh {
+	/** List of resources available to the root hub. */
+	hw_resource_list_t resource_list;
+	/** The only resource in the RH resource list */
+	hw_resource_t io_regs;
+} rh_t;
+
+int rh_init(
+    rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/transfer_list.c
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/transfer_list.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver transfer list implementation
+ */
+#include <errno.h>
+#include <usb/debug.h>
+#include <arch/barrier.h>
+
+
+#include "transfer_list.h"
+#include "batch.h"
+
+static void transfer_list_remove_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch);
+/*----------------------------------------------------------------------------*/
+/** Initialize transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ * @param[in] name Name of the new list.
+ * @return Error code
+ *
+ * Allocates memory for internal qh_t structure.
+ */
+int transfer_list_init(transfer_list_t *instance, const char *name)
+{
+	assert(instance);
+	instance->name = name;
+	instance->queue_head = malloc32(sizeof(qh_t));
+	if (!instance->queue_head) {
+		usb_log_error("Failed to allocate queue head.\n");
+		return ENOMEM;
+	}
+	const uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
+	usb_log_debug2("Transfer list %s setup with QH: %p (%#" PRIx32" ).\n",
+	    name, instance->queue_head, queue_head_pa);
+
+	qh_init(instance->queue_head);
+	list_initialize(&instance->batch_list);
+	fibril_mutex_initialize(&instance->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Dispose transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ *
+ * Frees memory of the internal qh_t structure.
+ */
+void transfer_list_fini(transfer_list_t *instance)
+{
+	assert(instance);
+	free32(instance->queue_head);
+}
+/** Set the next list in transfer list chain.
+ *
+ * @param[in] instance List to lead.
+ * @param[in] next List to append.
+ * @return Error code
+ *
+ * Does not check whether this replaces an existing list .
+ */
+void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
+{
+	assert(instance);
+	assert(instance->queue_head);
+	assert(next);
+	/* Set queue_head.next to point to the follower */
+	qh_set_next_qh(instance->queue_head, next->queue_head);
+}
+/*----------------------------------------------------------------------------*/
+/** Add transfer batch to the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] batch Transfer batch to submit.
+ *
+ * The batch is added to the end of the list and queue.
+ */
+void transfer_list_add_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
+
+	fibril_mutex_lock(&instance->guard);
+
+	qh_t *last_qh = NULL;
+	/* Add to the hardware queue. */
+	if (list_empty(&instance->batch_list)) {
+		/* There is nothing scheduled */
+		last_qh = instance->queue_head;
+	} else {
+		/* There is something scheduled */
+		usb_transfer_batch_t *last = usb_transfer_batch_from_link(
+		    list_last(&instance->batch_list));
+		last_qh = batch_qh(last);
+	}
+	const uint32_t pa = addr_to_phys(batch_qh(batch));
+	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
+
+	/* Make sure all data in the batch are written */
+	write_barrier();
+
+	/* keep link */
+	batch_qh(batch)->next = last_qh->next;
+	qh_set_next_qh(last_qh, batch_qh(batch));
+
+	/* Make sure the pointer is updated */
+	write_barrier();
+
+	/* Add to the driver's list */
+	list_append(&batch->link, &instance->batch_list);
+
+	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
+	    batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name);
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Add completed batches to the provided list.
+ *
+ * @param[in] instance List to use.
+ * @param[in] done list to fill
+ */
+void transfer_list_remove_finished(transfer_list_t *instance, list_t *done)
+{
+	assert(instance);
+	assert(done);
+
+	fibril_mutex_lock(&instance->guard);
+	link_t *current = instance->batch_list.head.next;
+	while (current != &instance->batch_list.head) {
+		link_t * const next = current->next;
+		usb_transfer_batch_t *batch =
+		    usb_transfer_batch_from_link(current);
+
+		if (batch_is_complete(batch)) {
+			/* Save for processing */
+			transfer_list_remove_batch(instance, batch);
+			list_append(current, done);
+		}
+		current = next;
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Walk the list and finish all batches with EINTR.
+ *
+ * @param[in] instance List to use.
+ */
+void transfer_list_abort_all(transfer_list_t *instance)
+{
+	fibril_mutex_lock(&instance->guard);
+	while (!list_empty(&instance->batch_list)) {
+		link_t * const current = list_first(&instance->batch_list);
+		usb_transfer_batch_t *batch =
+		    usb_transfer_batch_from_link(current);
+		transfer_list_remove_batch(instance, batch);
+		usb_transfer_batch_finish_error(batch, EINTR);
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Remove a transfer batch from the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] batch Transfer batch to remove.
+ *
+ * Does not lock the transfer list, caller is responsible for that.
+ */
+void transfer_list_remove_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(instance->queue_head);
+	assert(batch);
+	assert(batch_qh(batch));
+	assert(fibril_mutex_is_locked(&instance->guard));
+
+	usb_log_debug2(
+	    "Queue %s: removing batch(%p).\n", instance->name, batch);
+
+	const char *qpos = NULL;
+	qh_t *prev_qh = NULL;
+	/* Remove from the hardware queue */
+	if (list_first(&instance->batch_list) == &batch->link) {
+		/* I'm the first one here */
+		prev_qh = instance->queue_head;
+		qpos = "FIRST";
+	} else {
+		/* The thing before me is a batch too */
+		usb_transfer_batch_t *prev =
+		    usb_transfer_batch_from_link(batch->link.prev);
+		prev_qh = batch_qh(prev);
+		qpos = "NOT FIRST";
+	}
+	assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
+	    == addr_to_phys(batch_qh(batch)));
+	prev_qh->next = batch_qh(batch)->next;
+
+	/* Make sure the pointer is updated */
+	write_barrier();
+
+	/* Remove from the batch list */
+	list_remove(&batch->link);
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) "
+	    "from %s, next: %x.\n",
+	    batch, USB_TRANSFER_BATCH_ARGS(*batch),
+	    qpos, instance->name, batch_qh(batch)->next);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/transfer_list.h
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/transfer_list.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver transfer list structure
+ */
+#ifndef DRV_UHCI_TRANSFER_LIST_H
+#define DRV_UHCI_TRANSFER_LIST_H
+
+#include <fibril_synch.h>
+#include <usb/host/batch.h>
+
+#include "hw_struct/queue_head.h"
+
+/** Structure maintaining both hw queue and software list
+ * of currently executed transfers
+ */
+typedef struct transfer_list {
+	/** Guard against multiple add/remove races */
+	fibril_mutex_t guard;
+	/** UHCI hw structure represeting this queue */
+	qh_t *queue_head;
+	/** Assigned name, for nicer debug output */
+	const char *name;
+	/** List of all batches in this list */
+	list_t batch_list;
+} transfer_list_t;
+
+void transfer_list_fini(transfer_list_t *instance);
+int transfer_list_init(transfer_list_t *instance, const char *name);
+void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
+void transfer_list_add_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch);
+void transfer_list_remove_finished(transfer_list_t *instance, list_t *done);
+void transfer_list_abort_all(transfer_list_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,286 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/interrupt.h>
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "uhci.h"
+#include "iface.h"
+#include "pci.h"
+
+#include "hc.h"
+#include "root_hub.h"
+
+/** Structure representing both functions of UHCI hc, USB host controller
+ * and USB root hub */
+typedef struct uhci {
+	/** Pointer to DDF represenation of UHCI host controller */
+	ddf_fun_t *hc_fun;
+	/** Pointer to DDF represenation of UHCI root hub */
+	ddf_fun_t *rh_fun;
+
+	/** Internal driver's represenation of UHCI host controller */
+	hc_t hc;
+	/** Internal driver's represenation of UHCI root hub */
+	rh_t rh;
+} uhci_t;
+
+static inline uhci_t * dev_to_uhci(const ddf_dev_t *dev)
+{
+	assert(dev);
+	assert(dev->driver_data);
+	return dev->driver_data;
+}
+/*----------------------------------------------------------------------------*/
+/** IRQ handling callback, forward status from call to diver structure.
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call from kernel.
+ */
+static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	assert(dev);
+	uhci_t *uhci = dev_to_uhci(dev);
+	hc_t *hc = &uhci->hc;
+	const uint16_t status = IPC_GET_ARG1(*call);
+	assert(hc);
+	hc_interrupt(hc, status);
+}
+/*----------------------------------------------------------------------------*/
+/** Operations supported by the HC driver */
+static ddf_dev_ops_t hc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
+};
+/*----------------------------------------------------------------------------*/
+/** Get address of the device identified by handle.
+ *
+ * @param[in] fun DDF instance of the function to use.
+ * @param[in] handle DDF handle of the driver seeking its USB address.
+ * @param[out] address Found address.
+ */
+static int usb_iface_get_address(
+    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
+{
+	assert(fun);
+	usb_device_keeper_t *manager = &dev_to_uhci(fun->dev)->hc.manager;
+	usb_address_t addr = usb_device_keeper_find(manager, handle);
+
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Gets handle of the respective hc.
+ *
+ * @param[in] fun DDF function of uhci device.
+ * @param[out] handle Host cotnroller handle.
+ * @return Error code.
+ */
+static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+	ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun;
+	assert(hc_fun);
+
+	if (handle != NULL)
+		*handle = hc_fun->handle;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** USB interface implementation used by RH */
+static usb_iface_t usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle,
+	.get_address = usb_iface_get_address
+};
+/*----------------------------------------------------------------------------*/
+/** Get root hub hw resources (I/O registers).
+ *
+ * @param[in] fun Root hub function.
+ * @return Pointer to the resource list used by the root hub.
+ */
+static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
+{
+	assert(fun);
+	rh_t *rh = fun->driver_data;
+	assert(rh);
+	return &rh->resource_list;
+}
+/*----------------------------------------------------------------------------*/
+/** Interface to provide the root hub driver with hw info */
+static hw_res_ops_t hw_res_iface = {
+	.get_resource_list = get_resource_list,
+	.enable_interrupt = NULL,
+};
+/*----------------------------------------------------------------------------*/
+/** RH function support for uhci_rhd */
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface,
+	.interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
+};
+/*----------------------------------------------------------------------------*/
+/** Initialize hc and rh DDF structures and their respective drivers.
+ *
+ * @param[in] device DDF instance of the device to use.
+ *
+ * This function does all the preparatory work for hc and rh drivers:
+ *  - gets device's hw resources
+ *  - disables UHCI legacy support (PCI config space)
+ *  - attempts to enable interrupts
+ *  - registers interrupt handler
+ */
+int device_setup_uhci(ddf_dev_t *device)
+{
+	assert(device);
+	uhci_t *instance = malloc(sizeof(uhci_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate OHCI driver.\n");
+		return ENOMEM;
+	}
+
+#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+if (ret != EOK) { \
+	if (instance->hc_fun) \
+		instance->hc_fun->ops = NULL; \
+		instance->hc_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) {\
+		instance->rh_fun->ops = NULL; \
+		instance->rh_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->rh_fun); \
+	} \
+	free(instance); \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
+
+	instance->rh_fun = NULL;
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc");
+	int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
+	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
+	instance->rh_fun->ops = &rh_ops;
+	instance->rh_fun->driver_data = &instance->rh;
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
+	int irq = 0;
+
+	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to get I/O addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
+	    (void *) reg_base, reg_size, irq);
+
+	ret = pci_disable_legacy(device);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
+
+	bool interrupts = false;
+#ifdef CONFIG_USBHC_NO_INTERRUPTS
+	usb_log_warning("Interrupts disabled in OS config, " \
+	    "falling back to polling.\n");
+#else
+	ret = pci_enable_interrupts(device);
+	if (ret != EOK) {
+		usb_log_warning("Failed to enable interrupts: %s.\n",
+		    str_error(ret));
+		usb_log_info("HW interrupts not available, " \
+		    "falling back to polling.\n");
+	} else {
+		usb_log_debug("Hw interrupts enabled.\n");
+		interrupts = true;
+	}
+#endif
+
+
+	ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret));
+
+#define CHECK_RET_FINI_RETURN(ret, message...) \
+if (ret != EOK) { \
+	hc_fini(&instance->hc); \
+	CHECK_RET_DEST_FREE_RETURN(ret, message); \
+	return ret; \
+} else (void)0
+
+	/* It does no harm if we register this on polling */
+	ret = register_interrupt_handler(device, irq, irq_handler,
+	    &instance->hc.interrupt_code);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to register interrupt handler: %s.\n",
+	    ret, str_error(ret));
+
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to bind UHCI device function: %s.\n",
+	    ret, str_error(ret));
+
+	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to add UHCI to HC class: %s.\n", str_error(ret));
+
+	ret = rh_init(&instance->rh, instance->rh_fun,
+	    (uintptr_t)instance->hc.registers + 0x10, 4);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
+
+	ret = ddf_fun_bind(instance->rh_fun);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
+
+	device->driver_data = instance;
+	return EOK;
+#undef CHECK_RET_FINI_RETURN
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/uhci.h
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/uhci.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,43 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver main structure for both host controller and root-hub.
+ */
+#ifndef DRV_UHCI_UHCI_H
+#define DRV_UHCI_UHCI_H
+#include <ddf/driver.h>
+
+int device_setup_uhci(ddf_dev_t *device);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/uhci.ma
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/uhci.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,29 @@
+10 pci/ven=8086&dev=7020
+10 pci/ven=8086&dev=7112
+
+10 pci/ven=8086&dev=27c8
+10 pci/ven=8086&dev=27c9
+10 pci/ven=8086&dev=27ca
+10 pci/ven=8086&dev=27cb
+
+10 pci/ven=8086&dev=2830
+10 pci/ven=8086&dev=2831
+10 pci/ven=8086&dev=2832
+10 pci/ven=8086&dev=2834
+10 pci/ven=8086&dev=2835
+
+10 pci/ven=8086&dev=2934
+10 pci/ven=8086&dev=2935
+10 pci/ven=8086&dev=2936
+10 pci/ven=8086&dev=2937
+10 pci/ven=8086&dev=2938
+10 pci/ven=8086&dev=2939
+
+10 pci/ven=8086&dev=24c2
+10 pci/ven=8086&dev=24c4
+10 pci/ven=8086&dev=24c7
+
+10 pci/ven=8086&dev=2688
+10 pci/ven=8086&dev=2689
+10 pci/ven=8086&dev=268a
+10 pci/ven=8086&dev=268b
Index: uspace/drv/bus/usb/uhci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,114 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_UTILS_MALLOC32_H
+#define DRV_UHCI_UTILS_MALLOC32_H
+
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <mem.h>
+#include <as.h>
+
+#define UHCI_STRCUTURES_ALIGNMENT 16
+#define UHCI_REQUIRED_PAGE_SIZE 4096
+
+
+/** Get physical address translation
+ *
+ * @param[in] addr Virtual address to translate
+ * @return Physical address if exists, NULL otherwise.
+ */
+static inline uintptr_t addr_to_phys(void *addr)
+{
+	if (addr == NULL)
+		return 0;
+
+	uintptr_t result;
+	const int ret = as_get_physical_mapping(addr, &result);
+	if (ret != EOK)
+		return 0;
+	return (result | ((uintptr_t)addr & 0xfff));
+}
+/*----------------------------------------------------------------------------*/
+/** Physical mallocator simulator
+ *
+ * @param[in] size Size of the required memory space
+ * @return Address of the alligned and big enough memory place, NULL on failure.
+ */
+static inline void * malloc32(size_t size) {
+	/* This works only when the host has less than 4GB of memory as
+	 * physical address needs to fit into 32 bits */
+
+	/* If we need more than one page there is no guarantee that the
+	 * memory will be continuous */
+	if (size > PAGE_SIZE)
+		return NULL;
+	/* Calculate alignment to make sure the block won't cross page
+	 * boundary */
+	size_t alignment = UHCI_STRCUTURES_ALIGNMENT;
+	while (alignment < size)
+		alignment *= 2;
+	return memalign(alignment, size);
+}
+/*----------------------------------------------------------------------------*/
+/** Physical mallocator simulator
+ *
+ * @param[in] addr Address of the place allocated by malloc32
+ */
+static inline void free32(void *addr) {
+	if (!addr)
+		return;
+	free(addr);
+}
+/*----------------------------------------------------------------------------*/
+/** Create 4KB page mapping
+ *
+ * @return Address of the mapped page, NULL on failure.
+ */
+static inline void * get_page(void)
+{
+	void *free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
+	if (free_address == 0)
+		return NULL;
+	void *ret = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
+		  AS_AREA_READ | AS_AREA_WRITE);
+	if (ret != free_address)
+		return NULL;
+	return ret;
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/Makefile
===================================================================
--- uspace/drv/bus/usb/uhcirh/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhcirh/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,48 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = uhcirh
+
+SOURCES = \
+	main.c \
+	port.c \
+	root_hub.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/uhcirh/main.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhcirh/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,182 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI root hub initialization routines
+ */
+
+#include <ddf/driver.h>
+#include <devman.h>
+#include <device/hw_res.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+#define NAME "uhcirh"
+
+static int hc_get_my_registers(const ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size);
+
+static int uhci_rh_add_device(ddf_dev_t *device);
+
+static driver_ops_t uhci_rh_driver_ops = {
+	.add_device = uhci_rh_add_device,
+};
+
+static driver_t uhci_rh_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_rh_driver_ops
+};
+
+/** Initialize global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS UHCI root hub driver.\n");
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	return ddf_driver_main(&uhci_rh_driver);
+}
+
+/** Initialize a new ddf driver instance of UHCI root hub.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int uhci_rh_add_device(ddf_dev_t *device)
+{
+	if (!device)
+		return EINVAL;
+
+	usb_log_debug2("uhci_rh_add_device(handle=%" PRIun ")\n",
+	    device->handle);
+
+	uintptr_t io_regs = 0;
+	size_t io_size = 0;
+	uhci_root_hub_t *rh = NULL;
+	int ret = EOK;
+
+#define CHECK_RET_FREE_RH_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	if (rh) \
+		free(rh); \
+	return ret; \
+} else (void)0
+
+	ret = hc_get_my_registers(device, &io_regs, &io_size);
+	CHECK_RET_FREE_RH_RETURN(ret,
+	    "Failed to get registers from HC: %s.\n", str_error(ret));
+	usb_log_debug("I/O regs at %p (size %zuB).\n",
+	    (void *) io_regs, io_size);
+
+	rh = malloc(sizeof(uhci_root_hub_t));
+	ret = (rh == NULL) ? ENOMEM : EOK;
+	CHECK_RET_FREE_RH_RETURN(ret,
+	    "Failed to allocate rh driver instance.\n");
+
+	ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
+	CHECK_RET_FREE_RH_RETURN(ret,
+	    "Failed(%d) to initialize rh driver instance: %s.\n",
+	    ret, str_error(ret));
+
+	device->driver_data = rh;
+	usb_log_info("Controlling root hub '%s' (%" PRIun ").\n",
+	    device->name, device->handle);
+	return EOK;
+}
+
+/** Get address of I/O registers.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the memory range.
+ * @param[out] io_reg_size Size of the memory range.
+ * @return Error code.
+ */
+int hc_get_my_registers(
+    const ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
+{
+	assert(dev);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	hw_resource_list_t hw_resources;
+	const int ret = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (ret != EOK) {
+		async_hangup(parent_sess);
+		return ret;
+	}
+	
+	uintptr_t io_address = 0;
+	size_t io_size = 0;
+	bool io_found = false;
+	
+	size_t i = 0;
+	for (; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		if (res->type == IO_RANGE) {
+			io_address = res->res.io_range.address;
+			io_size = res->res.io_range.size;
+			io_found = true;
+		}
+	
+	}
+	async_hangup(parent_sess);
+	
+	if (!io_found)
+		return ENOENT;
+	
+	if (io_reg_address != NULL)
+		*io_reg_address = io_address;
+	
+	if (io_reg_size != NULL)
+		*io_reg_size = io_size;
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/port.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/port.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhcirh/port.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,355 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI root hub port routines
+ */
+#include <libarch/ddi.h>  /* pio_read and pio_write */
+#include <fibril_synch.h> /* async_usleep */
+#include <errno.h>
+#include <str_error.h>
+#include <async.h>
+
+#include <usb/usb.h>    /* usb_address_t */
+#include <usb/dev/hub.h>    /* usb_hc_new_device_wrapper */
+#include <usb/debug.h>
+
+#include "port.h"
+
+static int uhci_port_check(void *port);
+static int uhci_port_reset_enable(int portno, void *arg);
+static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
+static int uhci_port_remove_device(uhci_port_t *port);
+static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
+static void uhci_port_print_status(
+    uhci_port_t *port, const port_status_t value);
+
+/** Register reading helper function.
+ *
+ * @param[in] port Structure to use.
+ * @return Error code. (Always EOK)
+ */
+static inline port_status_t uhci_port_read_status(uhci_port_t *port)
+{
+	assert(port);
+	return pio_read_16(port->address);
+}
+/*----------------------------------------------------------------------------*/
+/** Register writing helper function.
+ *
+ * @param[in] port Structure to use.
+ * @param[in] val New register value.
+ * @return Error code. (Always EOK)
+ */
+static inline void uhci_port_write_status(uhci_port_t *port, port_status_t val)
+{
+	assert(port);
+	pio_write_16(port->address, val);
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI root hub port instance.
+ *
+ * @param[in] port Memory structure to use.
+ * @param[in] address Address of I/O register.
+ * @param[in] number Port number.
+ * @param[in] usec Polling interval.
+ * @param[in] rh Pointer to ddf instance of the root hub driver.
+ * @return Error code.
+ *
+ * Creates and starts the polling fibril.
+ */
+int uhci_port_init(uhci_port_t *port,
+    port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh)
+{
+	assert(port);
+	char *id_string;
+	asprintf(&id_string, "Port (%p - %u)", port, number);
+	if (id_string == NULL) {
+		return ENOMEM;
+	}
+
+	port->id_string = id_string;
+	port->address = address;
+	port->number = number;
+	port->wait_period_usec = usec;
+	port->attached_device = 0;
+	port->rh = rh;
+
+	int ret =
+	    usb_hc_connection_initialize_from_device(&port->hc_connection, rh);
+	if (ret != EOK) {
+		usb_log_error("%s: failed to initialize connection to HC.",
+		    port->id_string);
+		free(id_string);
+		return ret;
+	}
+
+	port->checker = fibril_create(uhci_port_check, port);
+	if (port->checker == 0) {
+		usb_log_error("%s: failed to create polling fibril.",
+		    port->id_string);
+		free(id_string);
+		return ENOMEM;
+	}
+
+	fibril_add_ready(port->checker);
+	usb_log_debug("%s: Started polling fibril (%" PRIun ").\n",
+	    port->id_string, port->checker);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Cleanup UHCI root hub port instance.
+ *
+ * @param[in] port Memory structure to use.
+ *
+ * Stops the polling fibril.
+ */
+void uhci_port_fini(uhci_port_t *port)
+{
+	assert(port);
+	free(port->id_string);
+	// TODO: Kill fibril here
+	return;
+}
+/*----------------------------------------------------------------------------*/
+/** Periodically checks port status and reports new devices.
+ *
+ * @param[in] port Port structure to use.
+ * @return Error code.
+ */
+int uhci_port_check(void *port)
+{
+	uhci_port_t *instance = port;
+	assert(instance);
+
+	while (1) {
+		async_usleep(instance->wait_period_usec);
+
+		/* Read register value */
+		const port_status_t port_status =
+		    uhci_port_read_status(instance);
+
+		/* Print the value if it's interesting */
+		if (port_status & ~STATUS_ALWAYS_ONE)
+			uhci_port_print_status(instance, port_status);
+
+		if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
+			continue;
+
+		usb_log_debug("%s: Connected change detected: %x.\n",
+		    instance->id_string, port_status);
+
+		/* Remove any old device */
+		if (instance->attached_device) {
+			usb_log_debug2("%s: Removing device.\n",
+			    instance->id_string);
+			uhci_port_remove_device(instance);
+		}
+
+		int ret =
+		    usb_hc_connection_open(&instance->hc_connection);
+		if (ret != EOK) {
+			usb_log_error("%s: Failed to connect to HC.",
+			    instance->id_string);
+			continue;
+		}
+
+		if ((port_status & STATUS_CONNECTED) != 0) {
+			/* New device */
+			const usb_speed_t speed =
+			    ((port_status & STATUS_LOW_SPEED) != 0) ?
+			    USB_SPEED_LOW : USB_SPEED_FULL;
+			uhci_port_new_device(instance, speed);
+		} else {
+			/* Write one to WC bits, to ack changes */
+			uhci_port_write_status(instance, port_status);
+			usb_log_debug("%s: status change ACK.\n",
+			    instance->id_string);
+		}
+
+		ret = usb_hc_connection_close(&instance->hc_connection);
+		if (ret != EOK) {
+			usb_log_error("%s: Failed to disconnect.",
+			    instance->id_string);
+		}
+	}
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Callback for enabling port during adding a new device.
+ *
+ * @param portno Port number (unused).
+ * @param arg Pointer to uhci_port_t of port with the new device.
+ * @return Error code.
+ *
+ * Resets and enables the ub port.
+ */
+int uhci_port_reset_enable(int portno, void *arg)
+{
+	uhci_port_t *port = arg;
+	assert(port);
+
+	usb_log_debug2("%s: new_device_enable_port.\n", port->id_string);
+
+	/*
+	 * Resets from root ports should be nominally 50ms (USB spec 7.1.7.3)
+	 */
+	{
+		usb_log_debug("%s: Reset Signal start.\n", port->id_string);
+		port_status_t port_status = uhci_port_read_status(port);
+		port_status |= STATUS_IN_RESET;
+		uhci_port_write_status(port, port_status);
+		async_usleep(50000);
+		port_status = uhci_port_read_status(port);
+		port_status &= ~STATUS_IN_RESET;
+		uhci_port_write_status(port, port_status);
+		while (uhci_port_read_status(port) & STATUS_IN_RESET);
+	}
+	/* PIO delay, should not be longer than 3ms as the device might
+	 * enter suspend state. */
+	udelay(10);
+	/* Enable the port. */
+	uhci_port_set_enabled(port, true);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize and report connected device.
+ *
+ * @param[in] port Port structure to use.
+ * @param[in] speed Detected speed.
+ * @return Error code.
+ *
+ * Uses libUSB function to do the actual work.
+ */
+int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed)
+{
+	assert(port);
+	assert(usb_hc_connection_is_opened(&port->hc_connection));
+
+	usb_log_debug("%s: Detected new device.\n", port->id_string);
+
+	int ret, count = 0;
+	usb_address_t dev_addr;
+	do {
+		ret = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
+		    speed, uhci_port_reset_enable, port->number, port,
+		    &dev_addr, &port->attached_device, NULL, NULL, NULL);
+	} while (ret != EOK && ++count < 4);
+
+	if (ret != EOK) {
+		usb_log_error("%s: Failed(%d) to add device: %s.\n",
+		    port->id_string, ret, str_error(ret));
+		uhci_port_set_enabled(port, false);
+		return ret;
+	}
+
+	usb_log_info("New device at port %u, address %d (handle %" PRIun ").\n",
+	    port->number, dev_addr, port->attached_device);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Remove device.
+ *
+ * @param[in] port Memory structure to use.
+ * @return Error code.
+ *
+ * Does not work, DDF does not support device removal.
+ * Does not even free used USB address (it would be dangerous if tis driver
+ * is still running).
+ */
+int uhci_port_remove_device(uhci_port_t *port)
+{
+	usb_log_error("%s: Don't know how to remove device %" PRIun ".\n",
+	    port->id_string, port->attached_device);
+	port->attached_device = 0;
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+/** Enable or disable root hub port.
+ *
+ * @param[in] port Port structure to use.
+ * @param[in] enabled Port status to set.
+ * @return Error code. (Always EOK)
+ */
+int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
+{
+	assert(port);
+
+	/* Read register value */
+	port_status_t port_status = uhci_port_read_status(port);
+
+	/* Set enabled bit */
+	if (enabled) {
+		port_status |= STATUS_ENABLED;
+	} else {
+		port_status &= ~STATUS_ENABLED;
+	}
+
+	/* Write new value. */
+	uhci_port_write_status(port, port_status);
+
+	/* Wait for port to become enabled */
+	do {
+		port_status = uhci_port_read_status(port);
+	} while ((port_status & STATUS_CONNECTED) &&
+	    !(port_status & STATUS_ENABLED));
+
+	usb_log_debug("%s: %sabled port.\n",
+		port->id_string, enabled ? "En" : "Dis");
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Print the port status value in a human friendly way
+ *
+ * @param[in] port Port structure to use.
+ * @param[in] value Port register value to print.
+ * @return Error code. (Always EOK)
+ */
+void uhci_port_print_status(uhci_port_t *port, const port_status_t value)
+{
+	assert(port);
+	usb_log_debug2("%s Port status(%#x):%s%s%s%s%s%s%s%s%s%s%s.\n",
+	    port->id_string, value,
+	    (value & STATUS_SUSPEND) ? " SUSPENDED," : "",
+	    (value & STATUS_RESUME) ? " IN RESUME," : "",
+	    (value & STATUS_IN_RESET) ? " IN RESET," : "",
+	    (value & STATUS_LINE_D_MINUS) ? " VD-," : "",
+	    (value & STATUS_LINE_D_PLUS) ? " VD+," : "",
+	    (value & STATUS_LOW_SPEED) ? " LOWSPEED," : "",
+	    (value & STATUS_ENABLED_CHANGED) ? " ENABLED-CHANGE," : "",
+	    (value & STATUS_ENABLED) ? " ENABLED," : "",
+	    (value & STATUS_CONNECTED_CHANGED) ? " CONNECTED-CHANGE," : "",
+	    (value & STATUS_CONNECTED) ? " CONNECTED," : "",
+	    (value & STATUS_ALWAYS_ONE) ? " ALWAYS ONE" : " ERR: NO ALWAYS ONE"
+	);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/port.h
===================================================================
--- uspace/drv/bus/usb/uhcirh/port.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhcirh/port.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,77 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI root hub port routines
+ */
+#ifndef DRV_UHCI_PORT_H
+#define DRV_UHCI_PORT_H
+
+#include <stdint.h>
+#include <fibril.h>
+#include <ddf/driver.h>
+#include <usb/hc.h> /* usb_hc_connection_t */
+
+typedef uint16_t port_status_t;
+#define STATUS_CONNECTED         (1 << 0)
+#define STATUS_CONNECTED_CHANGED (1 << 1)
+#define STATUS_ENABLED           (1 << 2)
+#define STATUS_ENABLED_CHANGED   (1 << 3)
+#define STATUS_LINE_D_PLUS       (1 << 4)
+#define STATUS_LINE_D_MINUS      (1 << 5)
+#define STATUS_RESUME            (1 << 6)
+#define STATUS_ALWAYS_ONE        (1 << 7)
+
+#define STATUS_LOW_SPEED (1 <<  8)
+#define STATUS_IN_RESET  (1 <<  9)
+#define STATUS_SUSPEND   (1 << 12)
+
+/** UHCI port structure */
+typedef struct uhci_port {
+	const char *id_string;
+	port_status_t *address;
+	unsigned number;
+	unsigned wait_period_usec;
+	usb_hc_connection_t hc_connection;
+	ddf_dev_t *rh;
+	devman_handle_t attached_device;
+	fid_t checker;
+} uhci_port_t;
+
+int uhci_port_init(
+    uhci_port_t *port, port_status_t *address, unsigned number,
+    unsigned usec, ddf_dev_t *rh);
+
+void uhci_port_fini(uhci_port_t *port);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/root_hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhcirh/root_hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI root hub driver
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <ddi.h>
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+/** Initialize UHCI root hub instance.
+ *
+ * @param[in] instance Driver memory structure to use.
+ * @param[in] addr Address of I/O registers.
+ * @param[in] size Size of available I/O space.
+ * @param[in] rh Pointer to DDF instance of the root hub driver.
+ * @return Error code.
+ */
+int uhci_root_hub_init(
+  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
+{
+	assert(instance);
+	assert(rh);
+
+	/* Allow access to root hub port registers */
+	assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);
+	port_status_t *regs;
+	int ret = pio_enable(addr, size, (void**)&regs);
+	if (ret < 0) {
+		usb_log_error(
+		    "Failed(%d) to gain access to port registers at %p: %s.\n",
+		    ret, regs, str_error(ret));
+		return ret;
+	}
+
+	/* Initialize root hub ports */
+	unsigned i = 0;
+	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
+		ret = uhci_port_init(
+		    &instance->ports[i], &regs[i], i, ROOT_HUB_WAIT_USEC, rh);
+		if (ret != EOK) {
+			unsigned j = 0;
+			for (;j < i; ++j)
+				uhci_port_fini(&instance->ports[j]);
+			return ret;
+		}
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Cleanup UHCI root hub instance.
+ *
+ * @param[in] instance Root hub structure to use.
+ */
+void uhci_root_hub_fini(uhci_root_hub_t* instance)
+{
+	assert(instance);
+	unsigned i = 0;
+	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
+		uhci_port_fini(&instance->ports[i]);
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/root_hub.h
===================================================================
--- uspace/drv/bus/usb/uhcirh/root_hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhcirh/root_hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,57 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_ROOT_HUB_H
+#define DRV_UHCI_ROOT_HUB_H
+
+#include <ddf/driver.h>
+
+#include "port.h"
+
+#define UHCI_ROOT_HUB_PORT_COUNT 2
+#define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */
+
+/** UHCI root hub drvier structure */
+typedef struct root_hub {
+	/** Ports provided by the hub */
+	uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
+} uhci_root_hub_t;
+
+int uhci_root_hub_init(
+    uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
+
+void uhci_root_hub_fini(uhci_root_hub_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/uhcirh.ma
===================================================================
--- uspace/drv/bus/usb/uhcirh/uhcirh.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/uhcirh/uhcirh.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 usb&uhci&root-hub
Index: uspace/drv/bus/usb/usbflbk/Makefile
===================================================================
--- uspace/drv/bus/usb/usbflbk/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbflbk/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,46 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbflbk
+
+SOURCES = \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbflbk/main.c
===================================================================
--- uspace/drv/bus/usb/usbflbk/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbflbk/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,95 @@
+/*
+ * 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 drvusbfallback
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB fallback driver.
+ */
+#include <usb/dev/driver.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+
+#define NAME "usbflbk"
+
+/** Callback when new device is attached and recognized by DDF.
+ *
+ * @param dev Representation of a generic DDF device.
+ * @return Error code.
+ */
+static int usbfallback_add_device(usb_device_t *dev)
+{
+	int rc;
+	const char *fun_name = "ctl";
+
+	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
+	    fun_name);
+	if (ctl_fun == NULL) {
+		usb_log_error("Failed to create control function.\n");
+		return ENOMEM;
+	}
+	rc = ddf_fun_bind(ctl_fun);
+	if (rc != EOK) {
+		usb_log_error("Failed to bind control function: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	usb_log_info("Pretending to control %s `%s'" \
+	    " (node `%s', handle %" PRIun ").\n",
+	    dev->interface_no < 0 ? "device" : "interface",
+	    dev->ddf_dev->name, fun_name, dev->ddf_dev->handle);
+
+	return EOK;
+}
+
+/** USB fallback driver ops. */
+static usb_driver_ops_t usbfallback_driver_ops = {
+	.add_device = usbfallback_add_device,
+};
+
+/** USB fallback driver. */
+static usb_driver_t usbfallback_driver = {
+	.name = NAME,
+	.ops = &usbfallback_driver_ops,
+	.endpoints = NULL
+};
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&usbfallback_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbflbk/usbflbk.ma
===================================================================
--- uspace/drv/bus/usb/usbflbk/usbflbk.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbflbk/usbflbk.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,2 @@
+10 usb&fallback
+10 usb&interface&fallback
Index: uspace/drv/bus/usb/usbhid/Makefile
===================================================================
--- uspace/drv/bus/usb/usbhid/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2010-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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I. \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbhid
+
+SUBDRIVER_SOURCES = \
+	kbd/conv.c \
+	kbd/kbddev.c \
+	kbd/kbdrepeat.c \
+	mouse/mousedev.c \
+	multimedia/multimedia.c \
+	multimedia/keymap.c
+
+SOURCES = \
+	main.c \
+	usbhid.c \
+	subdrivers.c \
+	generic/hiddev.c \
+	$(SUBDRIVER_SOURCES)
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID driver API.
+ */
+
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+
+#include <usbhid_iface.h>
+
+#include "hiddev.h"
+#include "usbhid.h"
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.flags = 0
+};
+
+const char *HID_GENERIC_FUN_NAME = "hid";
+const char *HID_GENERIC_CLASS_NAME = "hid";
+
+/*----------------------------------------------------------------------------*/
+
+static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
+
+static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
+    size_t size, size_t *act_size, int *event_nr, unsigned int flags);
+
+static int usb_generic_hid_client_connected(ddf_fun_t *fun);
+
+static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun);
+
+static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
+    size_t size, size_t *actual_size);
+
+/*----------------------------------------------------------------------------*/
+
+static usbhid_iface_t usb_generic_iface = {
+	.get_event = usb_generic_hid_get_event,
+	.get_event_length = usb_generic_hid_get_event_length,
+	.get_report_descriptor_length = usb_generic_get_report_descriptor_length,
+	.get_report_descriptor = usb_generic_get_report_descriptor
+};
+
+static ddf_dev_ops_t usb_generic_hid_ops = {
+	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
+	.open = usb_generic_hid_client_connected
+};
+
+/*----------------------------------------------------------------------------*/
+
+static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
+{
+	usb_log_debug2("Generic HID: Get event length (fun: %p, "
+	    "fun->driver_data: %p.\n", fun, fun->driver_data);
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		return 0;
+	}
+
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
+	    hid_dev, hid_dev->max_input_report_size);
+	
+	return hid_dev->max_input_report_size;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
+    size_t size, size_t *act_size, int *event_nr, unsigned int flags)
+{
+	usb_log_debug2("Generic HID: Get event.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL || buffer == NULL
+	    || act_size == NULL || event_nr == NULL) {
+		usb_log_debug("No function");
+		return EINVAL;
+	}
+
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	if (hid_dev->input_report_size > size) {
+		usb_log_debug("input_report_size > size (%zu, %zu)\n", 
+		    hid_dev->input_report_size, size);
+		return EINVAL;	// TODO: other error code
+	}
+	
+	/*! @todo This should probably be somehow atomic. */
+	memcpy(buffer, hid_dev->input_report, 
+	    hid_dev->input_report_size);
+	*act_size = hid_dev->input_report_size;
+	*event_nr = usb_hid_report_number(hid_dev);
+	
+	usb_log_debug2("OK\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
+{
+	usb_log_debug("Generic HID: Get report descriptor length.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		usb_log_debug("No function");
+		return EINVAL;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	usb_log_debug2("hid_dev->report_desc_size = %zu\n", 
+	    hid_dev->report_desc_size);
+	
+	return hid_dev->report_desc_size;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
+    size_t size, size_t *actual_size)
+{
+	usb_log_debug2("Generic HID: Get report descriptor.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		usb_log_debug("No function");
+		return EINVAL;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	if (hid_dev->report_desc_size > size) {
+		return EINVAL;
+	}
+	
+	memcpy(desc, hid_dev->report_desc, hid_dev->report_desc_size);
+	*actual_size = hid_dev->report_desc_size;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_client_connected(ddf_fun_t *fun)
+{
+	usb_log_debug("Generic HID: Client connected.\n");
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)
+{	
+	/* Create the function exposed under /dev/devices. */
+	/** @todo Generate numbers for the devices? */
+	usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_GENERIC_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	fun->ops = &usb_generic_hid_ops;
+	fun->driver_data = hid_dev;
+
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
+{
+	if (hid_dev == NULL) {
+		return EINVAL;
+	}
+	
+	return usb_generic_hid_create_function(hid_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data)
+{
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID driver API.
+ */
+
+#ifndef USB_HID_HIDDDEV_H_
+#define USB_HID_HIDDDEV_H_
+
+#include <usb/dev/driver.h>
+
+struct usb_hid_dev;
+
+usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
+
+const char *HID_GENERIC_FUN_NAME;
+const char *HID_GENERIC_CLASS_NAME;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_generic_hid_init(struct usb_hid_dev *hid_dev, void **data);
+
+bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev, void *data);
+
+#endif // USB_HID_HIDDDEV_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/conv.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/conv.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/kbd/conv.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB scancode parser.
+ */
+
+#include <io/keycode.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include "conv.h"
+
+/**
+ * Mapping between USB HID key codes (from HID Usage Tables) and corresponding
+ * HelenOS key codes.
+ */
+static int scanmap_simple[255] = {
+
+//	[0x29] = KC_BACKTICK,
+
+//	[0x02] = KC_1,
+//	[0x03] = KC_2,
+	[0x04] = KC_A,
+	[0x05] = KC_B,
+	[0x06] = KC_C,
+	[0x07] = KC_D,
+	[0x08] = KC_E,
+	[0x09] = KC_F,
+	[0x0a] = KC_G,
+	[0x0b] = KC_H,
+	[0x0c] = KC_I,
+	[0x0d] = KC_J,
+	[0x0e] = KC_K,
+	[0x0f] = KC_L,
+	[0x10] = KC_M,
+	[0x11] = KC_N,
+	[0x12] = KC_O,
+	[0x13] = KC_P,
+	[0x14] = KC_Q,
+	[0x15] = KC_R,
+	[0x16] = KC_S,
+	[0x17] = KC_T,
+	[0x18] = KC_U,
+	[0x19] = KC_V,
+	[0x1a] = KC_W,
+	[0x1b] = KC_X,
+	[0x1c] = KC_Y,
+	[0x1d] = KC_Z,
+
+	[0x1e] = KC_1,
+	[0x1f] = KC_2,
+	[0x20] = KC_3,
+	[0x21] = KC_4,
+	[0x22] = KC_5,
+	[0x23] = KC_6,
+	[0x24] = KC_7,
+	[0x25] = KC_8,
+	[0x26] = KC_9,
+	[0x27] = KC_0,
+	
+	[0x28] = KC_ENTER,
+	[0x29] = KC_ESCAPE,
+	[0x2a] = KC_BACKSPACE,
+	[0x2b] = KC_TAB,
+	[0x2c] = KC_SPACE,
+
+	[0x2d] = KC_MINUS,  // same as DASH? (- or _)
+	[0x2e] = KC_EQUALS,
+	[0x2f] = KC_LBRACKET,
+	[0x30] = KC_RBRACKET,
+	[0x31] = KC_BACKSLASH,
+	//[0x32] = KC_,	// TODO: HASH??? maybe same as 0x31 - backslash
+	[0x32] = KC_BACKSLASH,
+	[0x33] = KC_SEMICOLON,
+	[0x34] = KC_QUOTE,  // same as APOSTROPHE? (')
+	[0x35] = KC_BACKTICK,  // same as GRAVE ACCENT?? (`)
+	[0x36] = KC_COMMA,
+	[0x37] = KC_PERIOD,
+	[0x38] = KC_SLASH,
+
+	[0x39] = KC_CAPS_LOCK,
+	
+	[0x3a] = KC_F1,
+	[0x3b] = KC_F2,
+	[0x3c] = KC_F3,
+	[0x3d] = KC_F4,
+	[0x3e] = KC_F5,
+	[0x3f] = KC_F6,
+	[0x40] = KC_F7,
+	[0x41] = KC_F8,
+	[0x42] = KC_F9,
+	[0x43] = KC_F10,
+	[0x44] = KC_F11,
+	[0x45] = KC_F12,
+	
+	[0x46] = KC_PRTSCR,
+	[0x47] = KC_SCROLL_LOCK,
+	[0x48] = KC_PAUSE,
+	[0x49] = KC_INSERT,
+	[0x4a] = KC_HOME,
+	[0x4b] = KC_PAGE_UP,
+	[0x4c] = KC_DELETE,
+	[0x4d] = KC_END,
+	[0x4e] = KC_PAGE_DOWN,
+	[0x4f] = KC_RIGHT,
+	[0x50] = KC_LEFT,
+	[0x51] = KC_DOWN,
+	[0x52] = KC_UP,
+	
+	//[0x64] = // some funny key
+	
+	[0xe0] = KC_LCTRL,
+	[0xe1] = KC_LSHIFT,
+	[0xe2] = KC_LALT,
+	//[0xe3] = KC_L	// TODO: left GUI
+	[0xe4] = KC_RCTRL,
+	[0xe5] = KC_RSHIFT,
+	[0xe6] = KC_RALT,
+	//[0xe7] = KC_R	// TODO: right GUI
+	
+	[0x53] = KC_NUM_LOCK,
+	[0x54] = KC_NSLASH,
+	[0x55] = KC_NTIMES,
+	[0x56] = KC_NMINUS,
+	[0x57] = KC_NPLUS,
+	[0x58] = KC_NENTER,
+	[0x59] = KC_N1,
+	[0x5a] = KC_N2,
+	[0x5b] = KC_N3,
+	[0x5c] = KC_N4,
+	[0x5d] = KC_N5,
+	[0x5e] = KC_N6,
+	[0x5f] = KC_N7,
+	[0x60] = KC_N8,
+	[0x61] = KC_N9,
+	[0x62] = KC_N0,
+	[0x63] = KC_NPERIOD
+	
+};
+
+/**
+ * Translate USB HID key codes (from HID Usage Tables) to generic key codes
+ * recognized by HelenOS.
+ *
+ * @param scancode USB HID key code (from HID Usage Tables).
+ * 
+ * @retval HelenOS key code corresponding to the given USB HID key code.
+ */
+unsigned int usbhid_parse_scancode(int scancode)
+{
+	unsigned int key;
+	int *map = scanmap_simple;
+	size_t map_length = sizeof(scanmap_simple) / sizeof(int);
+
+	if ((scancode < 0) || ((size_t) scancode >= map_length))
+		return -1;
+
+	key = map[scancode];
+	
+	return key;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/conv.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/conv.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/kbd/conv.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB scancode parser.
+ */
+
+#ifndef USB_HID_CONV_H_
+#define USB_HID_CONV_H_
+
+unsigned int usbhid_parse_scancode(int scancode);
+
+#endif /* USB_HID_CONV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,865 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID keyboard device structure and API.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+
+#include <io/keycode.h>
+#include <io/console.h>
+#include <ipc/kbdev.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <fibril.h>
+#include <fibril_synch.h>
+
+#include <ddf/log.h>
+
+#include <usb/usb.h>
+#include <usb/dev/dp.h>
+#include <usb/dev/request.h>
+#include <usb/hid/hid.h>
+#include <usb/dev/pipes.h>
+#include <usb/debug.h>
+#include <usb/hid/hidparser.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/usages/core.h>
+#include <usb/hid/request.h>
+#include <usb/hid/hidreport.h>
+#include <usb/hid/usages/led.h>
+
+#include <usb/dev/driver.h>
+
+#include "kbddev.h"
+
+#include "conv.h"
+#include "kbdrepeat.h"
+
+#include "../usbhid.h"
+
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
+
+/*----------------------------------------------------------------------------*/
+
+static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
+
+static const uint8_t ERROR_ROLLOVER = 1;
+
+/** Default idle rate for keyboards. */
+static const uint8_t IDLE_RATE = 0;
+
+/** Delay before a pressed key starts auto-repeating. */
+static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
+
+/** Delay between two repeats of a pressed key when auto-repeating. */
+static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
+
+/*----------------------------------------------------------------------------*/
+
+/** Keyboard polling endpoint description for boot protocol class. */
+usb_endpoint_description_t usb_hid_kbd_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
+};
+
+const char *HID_KBD_FUN_NAME = "keyboard";
+const char *HID_KBD_CLASS_NAME = "keyboard";
+
+static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
+};
+
+static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
+    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
+        0x05, 0x01,  // Usage Page (Generic Desktop),
+        0x09, 0x06,  // Usage (Keyboard),
+        0xA1, 0x01,  // Collection (Application),
+        0x75, 0x01,  //   Report Size (1),
+        0x95, 0x08,  //   Report Count (8),       
+        0x05, 0x07,  //   Usage Page (Key Codes);
+        0x19, 0xE0,  //   Usage Minimum (224),
+        0x29, 0xE7,  //   Usage Maximum (231),
+        0x15, 0x00,  //   Logical Minimum (0),
+        0x25, 0x01,  //   Logical Maximum (1),
+        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
+	0x95, 0x01,  //   Report Count (1),
+        0x75, 0x08,  //   Report Size (8),
+        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
+        0x95, 0x05,  //   Report Count (5),
+        0x75, 0x01,  //   Report Size (1),
+        0x05, 0x08,  //   Usage Page (Page# for LEDs),
+        0x19, 0x01,  //   Usage Minimum (1),
+        0x29, 0x05,  //   Usage Maxmimum (5),
+        0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
+        0x95, 0x01,  //   Report Count (1),
+        0x75, 0x03,  //   Report Size (3),
+        0x91, 0x01,  //   Output (Constant),              ; LED report padding
+        0x95, 0x06,  //   Report Count (6),
+        0x75, 0x08,  //   Report Size (8),
+        0x15, 0x00,  //   Logical Minimum (0),
+        0x25, 0xff,  //   Logical Maximum (255),
+        0x05, 0x07,  //   Usage Page (Key Codes),
+        0x19, 0x00,  //   Usage Minimum (0),
+        0x29, 0xff,  //   Usage Maximum (255),
+        0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
+        0xC0           // End Collection
+
+};
+
+/*----------------------------------------------------------------------------*/
+
+typedef enum usb_kbd_flags {
+	USB_KBD_STATUS_UNINITIALIZED = 0,
+	USB_KBD_STATUS_INITIALIZED = 1,
+	USB_KBD_STATUS_TO_DESTROY = -1
+} usb_kbd_flags;
+
+/*----------------------------------------------------------------------------*/
+/* IPC method handler                                                         */
+/*----------------------------------------------------------------------------*/
+
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+
+/**
+ * Default handler for IPC methods not handled by DDF.
+ *
+ * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
+ * assumes the caller is the console and thus it stores IPC phone to it for 
+ * later use by the driver to notify about key events.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+static void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	int callback;
+	
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)fun->driver_data;
+	if (kbd_dev == NULL) {
+		usb_log_debug("default_connection_handler: "
+		    "Missing parameter.\n");
+		async_answer_0(icallid, EINVAL);
+		return;
+	}
+
+	switch (method) {
+	case IPC_M_CONNECT_TO_ME:
+		callback = IPC_GET_ARG5(*icall);
+
+		if (kbd_dev->console_phone != -1) {
+			usb_log_debug("default_connection_handler: "
+			    "console phone already set\n");
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		kbd_dev->console_phone = callback;
+		
+		usb_log_debug("default_connection_handler: OK\n");
+		async_answer_0(icallid, EOK);
+		break;
+	case KBDEV_SET_IND:
+		kbd_dev->mods = IPC_GET_ARG1(*icall);
+		usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
+		async_answer_0(icallid, EOK);
+		break;
+	default:
+		usb_log_debug("default_connection_handler: Wrong function.\n");
+		async_answer_0(icallid, EINVAL);
+		break;
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/* Key processing functions                                                   */
+/*----------------------------------------------------------------------------*/
+/**
+ * Handles turning of LED lights on and off.
+ *
+ * As with most other keyboards, the LED indicators in USB keyboards are
+ * driven by software. When state of some modifier changes, the input server
+ * will call us and tell us to update the LED state and what the new state
+ * should be.
+ *
+ * This functions sets the LED lights according to current settings of modifiers
+ * kept in the keyboard device structure.
+ *
+ * @param kbd_dev Keyboard device structure.
+ */
+static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
+{
+	if (kbd_dev->output_size == 0) {
+		return;
+	}
+
+	/* Reset the LED data. */
+	memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t));
+	usb_log_debug("Creating output report:\n");
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, kbd_dev->led_path, 
+	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+	    USB_HID_REPORT_TYPE_OUTPUT);
+	
+	while (field != NULL) {
+		
+		if ((field->usage == USB_HID_LED_NUM_LOCK) 
+		    && (kbd_dev->mods & KM_NUM_LOCK)){
+			field->value = 1;
+		}
+
+		if ((field->usage == USB_HID_LED_CAPS_LOCK) 
+		    && (kbd_dev->mods & KM_CAPS_LOCK)){
+			field->value = 1;
+		}
+
+		if ((field->usage == USB_HID_LED_SCROLL_LOCK) 
+		    && (kbd_dev->mods & KM_SCROLL_LOCK)){
+			field->value = 1;
+		}
+		
+		field = usb_hid_report_get_sibling(hid_dev->report, field,
+		    kbd_dev->led_path,  
+	    	USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+			USB_HID_REPORT_TYPE_OUTPUT);
+	}
+	
+	// TODO: what about the Report ID?
+	int rc = usb_hid_report_output_translate(hid_dev->report, 0,
+	    kbd_dev->output_buffer, kbd_dev->output_size);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error translating LED output to output report"
+		    ".\n");
+		return;
+	}
+	
+	usb_log_debug("Output report buffer: %s\n", 
+	    usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
+	        0));
+	
+	usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
+	    kbd_dev->output_buffer, kbd_dev->output_size);
+}
+
+/*----------------------------------------------------------------------------*/
+/** Send key event.
+ *
+ * @param kbd_dev Keyboard device structure.
+ * @param type Type of the event (press / release). Recognized values:
+ *             KEY_PRESS, KEY_RELEASE
+ * @param key Key code
+ */
+void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type, 
+    unsigned int key)
+{
+	usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
+	if (kbd_dev->console_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
+	
+	async_obsolete_msg_2(kbd_dev->console_phone, KBDEV_EVENT, type, key);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static inline int usb_kbd_is_lock(unsigned int key_code) 
+{
+	return (key_code == KC_NUM_LOCK
+	    || key_code == KC_SCROLL_LOCK
+	    || key_code == KC_CAPS_LOCK);
+}
+
+static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
+{
+	for (size_t i = 0; i < arr_size; i++) {
+		if (arr[i] == val) {
+			return i;
+		}
+	}
+
+	return (size_t) -1;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Checks if some keys were pressed or released and generates key events.
+ *
+ * An event is created only when key is pressed or released. Besides handling
+ * the events (usb_kbd_push_ev()), the auto-repeat fibril is notified about
+ * key presses and releases (see usb_kbd_repeat_start() and 
+ * usb_kbd_repeat_stop()).
+ *
+ * @param kbd_dev Keyboard device structure.
+ * @param key_codes Parsed keyboard report - codes of currently pressed keys 
+ *                  according to HID Usage Tables.
+ * @param count Number of key codes in report (size of the report).
+ *
+ * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
+ */
+static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
+    usb_kbd_t *kbd_dev)
+{
+	unsigned int key;
+	size_t i;
+	
+	/*
+	 * First of all, check if the kbd have reported phantom state.
+	 *
+	 * As there is no way to distinguish keys from modifiers, we do not have
+	 * a way to check that 'all keys report Error Rollover'. We thus check
+	 * if there is at least one such error and in such case we ignore the
+	 * whole input report.
+	 */
+	i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
+	    kbd_dev->key_count);
+	if (i != (size_t) -1) {
+		usb_log_debug("Detected phantom state.\n");
+		return;
+	}
+	
+	/*
+	 * Key releases
+	 */
+	for (i = 0; i < kbd_dev->key_count; i++) {
+		int32_t old_key = kbd_dev->keys_old[i];
+		/* Find the old key among currently pressed keys. */
+		size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
+		    kbd_dev->key_count);
+		/* If the key was not found, we need to signal release. */
+		if (pos == (size_t) -1) {
+			key = usbhid_parse_scancode(old_key);
+			if (!usb_kbd_is_lock(key)) {
+				usb_kbd_repeat_stop(kbd_dev, key);
+			}
+			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
+			usb_log_debug2("Key released: %u "
+			    "(USB code %" PRIu32 ")\n", key, old_key);
+		}
+	}
+	
+	/*
+	 * Key presses
+	 */
+	for (i = 0; i < kbd_dev->key_count; ++i) {
+		int32_t new_key = kbd_dev->keys[i];
+		/* Find the new key among already pressed keys. */
+		size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
+		    kbd_dev->key_count);
+		/* If the key was not found, we need to signal press. */
+		if (pos == (size_t) -1) {
+			key = usbhid_parse_scancode(kbd_dev->keys[i]);
+			if (!usb_kbd_is_lock(key)) {
+				usb_kbd_repeat_start(kbd_dev, key);
+			}
+			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
+			usb_log_debug2("Key pressed: %u "
+			    "(USB code %" PRIu32 ")\n", key, new_key);
+		}
+	}
+	
+	memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
+	
+	char key_buffer[512];
+	ddf_dump_buffer(key_buffer, 512,
+	    kbd_dev->keys_old, 4, kbd_dev->key_count, 0);
+	usb_log_debug2("Stored keys %s.\n", key_buffer);
+}
+
+/*----------------------------------------------------------------------------*/
+/* General kbd functions                                                      */
+/*----------------------------------------------------------------------------*/
+/**
+ * Processes data received from the device in form of report.
+ *
+ * This function uses the HID report parser to translate the data received from
+ * the device into generic USB HID key codes and into generic modifiers bitmap.
+ * The parser then calls the given callback (usb_kbd_process_keycodes()).
+ *
+ * @note Currently, only the boot protocol is supported.
+ *
+ * @param kbd_dev Keyboard device structure (must be initialized).
+ * @param buffer Data from the keyboard (i.e. the report).
+ * @param actual_size Size of the data from keyboard (report size) in bytes.
+ *
+ * @sa usb_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(),
+ *     usb_hid_parse_report().
+ */
+static void usb_kbd_process_data(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
+{
+	assert(hid_dev->report != NULL);
+	assert(hid_dev != NULL);
+	assert(kbd_dev != NULL);
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+
+	usb_hid_report_path_set_report_id (path, hid_dev->report_id);
+	
+	// fill in the currently pressed keys
+	
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, 
+	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    USB_HID_REPORT_TYPE_INPUT);
+	unsigned i = 0;
+	
+	while (field != NULL) {
+		usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
+		    field, field->value, field->usage);
+		
+		assert(i < kbd_dev->key_count);
+		
+		// save the key usage
+		if (field->value != 0) {
+			kbd_dev->keys[i] = field->usage;
+		}
+		else {
+			kbd_dev->keys[i] = 0;
+		}
+		usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
+		
+		++i;
+		field = usb_hid_report_get_sibling(hid_dev->report, field, path, 
+		    USB_HID_PATH_COMPARE_END 
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}
+	
+	usb_hid_report_path_free(path);
+	
+	usb_kbd_check_key_changes(hid_dev, kbd_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+/* HID/KBD structure manipulation                                             */
+/*----------------------------------------------------------------------------*/
+
+static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
+{
+	kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Creates a new USB/HID keyboard structure.
+ *
+ * The structure returned by this function is not initialized. Use 
+ * usb_kbd_init() to initialize it prior to polling.
+ *
+ * @return New uninitialized structure for representing a USB/HID keyboard or
+ *         NULL if not successful (memory error).
+ */
+static usb_kbd_t *usb_kbd_new(void)
+{
+	usb_kbd_t *kbd_dev = 
+	    (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
+
+	if (kbd_dev == NULL) {
+		usb_log_fatal("No memory!\n");
+		return NULL;
+	}
+	
+	kbd_dev->console_phone = -1;
+	kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
+	
+	return kbd_dev;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_kbd_create_function(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
+{
+	assert(hid_dev != NULL);
+	assert(hid_dev->usb_dev != NULL);
+	assert(kbd_dev != NULL);
+	
+	/* Create the function exposed under /dev/devices. */
+	usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_KBD_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/*
+	 * Store the initialized HID device and HID ops
+	 * to the DDF function.
+	 */
+	fun->ops = &kbd_dev->ops;
+	fun->driver_data = kbd_dev;
+
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("%s function created. Handle: %" PRIun "\n",
+	    HID_KBD_FUN_NAME, fun->handle);
+	
+	usb_log_debug("Adding DDF function to class %s...\n", 
+	    HID_KBD_CLASS_NAME);
+	rc = ddf_fun_add_to_class(fun, HID_KBD_CLASS_NAME);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class %s: %s.\n",
+		    HID_KBD_CLASS_NAME, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/* API functions                                                              */
+/*----------------------------------------------------------------------------*/
+/**
+ * Initialization of the USB/HID keyboard structure.
+ *
+ * This functions initializes required structures from the device's descriptors.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ *
+ * @param kbd_dev Keyboard device structure to be initialized.
+ * @param dev DDF device structure of the keyboard.
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if some parameter is not given.
+ * @return Other value inherited from function usbhid_dev_init().
+ */
+int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
+{
+	usb_log_debug("Initializing HID/KBD structure...\n");
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	usb_kbd_t *kbd_dev = usb_kbd_new();
+	if (kbd_dev == NULL) {
+		usb_log_error("Error while creating USB/HID KBD device "
+		    "structure.\n");
+		return ENOMEM;  // TODO: some other code??
+	}
+
+	/* Store link to HID device */
+	kbd_dev->hid_dev = hid_dev;
+	
+	/*
+	 * TODO: make more general
+	 */
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+	
+	usb_hid_report_path_set_report_id(path, 0);
+	
+	kbd_dev->key_count = usb_hid_report_size(
+	    hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT); 
+	usb_hid_report_path_free(path);
+	
+	usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
+	
+	kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
+	
+	if (kbd_dev->keys == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
+	kbd_dev->keys_old = 
+		(int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
+	
+	if (kbd_dev->keys_old == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev->keys);
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Output report
+	 */
+	kbd_dev->output_size = 0;
+	kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report, 
+	    &kbd_dev->output_size, 0);
+	if (kbd_dev->output_buffer == NULL) {
+		usb_log_warning("Error creating output report buffer.\n");
+		free(kbd_dev->keys);
+		return ENOMEM;
+	}
+	
+	usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
+	
+	kbd_dev->led_path = usb_hid_report_path();
+	usb_hid_report_path_append_item(
+	    kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
+	
+	kbd_dev->led_output_size = usb_hid_report_size(hid_dev->report, 
+	    0, USB_HID_REPORT_TYPE_OUTPUT);
+	
+	usb_log_debug("Output report size (in items): %zu\n", 
+	    kbd_dev->led_output_size);
+	
+	kbd_dev->led_data = (int32_t *)calloc(
+	    kbd_dev->led_output_size, sizeof(int32_t));
+	
+	if (kbd_dev->led_data == NULL) {
+		usb_log_warning("Error creating buffer for LED output report."
+		    "\n");
+		free(kbd_dev->keys);
+		usb_hid_report_output_free(kbd_dev->output_buffer);
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Modifiers and locks
+	 */
+	kbd_dev->modifiers = 0;
+	kbd_dev->mods = DEFAULT_ACTIVE_MODS;
+	kbd_dev->lock_keys = 0;
+	
+	/*
+	 * Autorepeat
+	 */
+	kbd_dev->repeat.key_new = 0;
+	kbd_dev->repeat.key_repeated = 0;
+	kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
+	kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
+	
+	kbd_dev->repeat_mtx = (fibril_mutex_t *)(
+	    malloc(sizeof(fibril_mutex_t)));
+	if (kbd_dev->repeat_mtx == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev->keys);
+		usb_hid_report_output_free(kbd_dev->output_buffer);
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
+	fibril_mutex_initialize(kbd_dev->repeat_mtx);
+	
+	// save the KBD device structure into the HID device structure
+	*data = kbd_dev;
+	
+	// set handler for incoming calls
+	kbd_dev->ops.default_handler = default_connection_handler;
+	
+	/*
+	 * Set LEDs according to initial setup.
+	 * Set Idle rate
+	 */
+	usb_kbd_set_led(hid_dev, kbd_dev);
+	
+	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, IDLE_RATE);
+	
+	/*
+	 * Create new fibril for auto-repeat
+	 */
+	fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
+	if (fid == 0) {
+		usb_log_error("Failed to start fibril for KBD auto-repeat");
+		return ENOMEM;
+	}
+	fibril_add_ready(fid);
+	
+	kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
+	usb_log_debug("HID/KBD device structure initialized.\n");
+	
+	usb_log_debug("Creating KBD function...\n");
+	int rc = usb_kbd_create_function(hid_dev, kbd_dev);
+	if (rc != EOK) {
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
+{
+	if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
+		// do not continue polling (???)
+		return false;
+	}
+	
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
+	assert(kbd_dev != NULL);
+	
+	// TODO: add return value from this function
+	usb_kbd_process_data(hid_dev, kbd_dev);
+	
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
+{
+	return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
+{
+	return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Properly destroys the USB/HID keyboard structure.
+ *
+ * @param kbd_dev Pointer to the structure to be destroyed.
+ */
+void usb_kbd_free(usb_kbd_t **kbd_dev)
+{
+	if (kbd_dev == NULL || *kbd_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_obsolete_hangup((*kbd_dev)->console_phone);
+	
+	if ((*kbd_dev)->repeat_mtx != NULL) {
+		//assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
+		// FIXME - the fibril_mutex_is_locked may not cause
+		// fibril scheduling
+		while (fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)) {}
+		free((*kbd_dev)->repeat_mtx);
+	}
+	
+	// free all buffers
+	if ((*kbd_dev)->keys != NULL) {
+		free((*kbd_dev)->keys);
+	}
+	if ((*kbd_dev)->keys_old != NULL) {
+		free((*kbd_dev)->keys_old);
+	}
+	if ((*kbd_dev)->led_data != NULL) {
+		free((*kbd_dev)->led_data);
+	}
+	if ((*kbd_dev)->led_path != NULL) {
+		usb_hid_report_path_free((*kbd_dev)->led_path);
+	}
+	if ((*kbd_dev)->output_buffer != NULL) {
+		usb_hid_report_output_free((*kbd_dev)->output_buffer);
+	}
+
+	free(*kbd_dev);
+	*kbd_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
+{
+	if (hid_dev == NULL) {
+		return;
+	}
+	
+	if (data != NULL) {
+		usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
+		if (usb_kbd_is_initialized(kbd_dev)) {
+			usb_kbd_mark_unusable(kbd_dev);
+		} else {
+			usb_kbd_free(&kbd_dev);
+		}
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
+{
+	int rc = usb_hid_parse_report_descriptor(hid_dev->report, 
+	    USB_KBD_BOOT_REPORT_DESCRIPTOR, 
+	    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to parse boot report descriptor: %s\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
+	
+	if (rc != EOK) {
+		usb_log_warning("Failed to set boot protocol to the device: "
+		    "%s\n", str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID keyboard device structure and API.
+ */
+
+#ifndef USB_HID_KBDDEV_H_
+#define USB_HID_KBDDEV_H_
+
+#include <stdint.h>
+
+#include <fibril_synch.h>
+
+#include <usb/hid/hid.h>
+#include <usb/hid/hidparser.h>
+#include <ddf/driver.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+
+#include "kbdrepeat.h"
+
+struct usb_hid_dev;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * USB/HID keyboard device type.
+ *
+ * Holds a reference to generic USB/HID device structure and keyboard-specific
+ * data, such as currently pressed keys, modifiers and lock keys.
+ *
+ * Also holds a IPC phone to the console (since there is now no other way to 
+ * communicate with it).
+ *
+ * @note Storing active lock keys in this structure results in their setting
+ *       being device-specific.
+ */
+typedef struct usb_kbd_t {
+	/** Link to HID device structure */
+	struct usb_hid_dev *hid_dev;
+
+	/** Previously pressed keys (not translated to key codes). */
+	int32_t *keys_old;
+	/** Currently pressed keys (not translated to key codes). */
+	int32_t *keys;
+	/** Count of stored keys (i.e. number of keys in the report). */
+	size_t key_count;
+	/** Currently pressed modifiers (bitmap). */
+	uint8_t modifiers;
+	
+	/** Currently active modifiers including locks. Sent to the console. */
+	unsigned mods;
+	
+	/** Currently active lock keys. */
+	unsigned lock_keys;
+	
+	/** IPC phone to the console device (for sending key events). */
+	int console_phone;
+	
+	/** @todo What is this actually? */
+	ddf_dev_ops_t ops;
+	
+	/** Information for auto-repeat of keys. */
+	usb_kbd_repeat_t repeat;
+	
+	/** Mutex for accessing the information about auto-repeat. */
+	fibril_mutex_t *repeat_mtx;
+	
+	uint8_t *output_buffer;
+	
+	size_t output_size;
+	
+	size_t led_output_size;
+	
+	usb_hid_report_path_t *led_path;
+	
+	int32_t *led_data;
+	
+	/** State of the structure (for checking before use). 
+	 * 
+	 * 0 - not initialized
+	 * 1 - initialized
+	 * -1 - ready for destroying
+	 */
+	int initialized;
+} usb_kbd_t;
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
+
+const char *HID_KBD_FUN_NAME;
+const char *HID_KBD_CLASS_NAME;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_init(struct usb_hid_dev *hid_dev, void **data);
+
+bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, void *data);
+
+int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
+
+int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev);
+
+void usb_kbd_free(usb_kbd_t **kbd_dev);
+
+void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
+    int type, unsigned int key);
+
+void usb_kbd_deinit(struct usb_hid_dev *hid_dev, void *data);
+
+int usb_kbd_set_boot_protocol(struct usb_hid_dev *hid_dev);
+
+#endif /* USB_HID_KBDDEV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID keyboard autorepeat facilities
+ */
+
+#include <fibril_synch.h>
+#include <io/keycode.h>
+#include <io/console.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "kbdrepeat.h"
+#include "kbddev.h"
+
+
+/** Delay between auto-repeat state checks when no key is being repeated. */
+static unsigned int CHECK_DELAY = 10000;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Main loop handling the auto-repeat of keys.
+ *
+ * This functions periodically checks if there is some key to be auto-repeated.
+ *
+ * If a new key is to be repeated, it uses the delay before first repeat stored
+ * in the keyboard structure to wait until the key has to start repeating.
+ *
+ * If the same key is still pressed, it uses the delay between repeats stored
+ * in the keyboard structure to wait until the key should be repeated.
+ * 
+ * If the currently repeated key is not pressed any more (
+ * usb_kbd_repeat_stop() was called), it stops repeating it and starts 
+ * checking again.
+ *
+ * @note For accessing the keyboard device auto-repeat information a fibril
+ *       mutex (repeat_mtx) from the @a kbd structure is used.
+ * 
+ * @param kbd Keyboard device structure.
+ */
+static void usb_kbd_repeat_loop(usb_kbd_t *kbd)
+{
+	unsigned int delay = 0;
+	
+	usb_log_debug("Starting autorepeat loop.\n");
+
+	while (true) {
+		// check if the kbd structure is usable
+		if (!usb_kbd_is_initialized(kbd)) {
+			if (usb_kbd_is_ready_to_destroy(kbd)) {
+				usb_kbd_free(&kbd);
+				assert(kbd == NULL);
+			}
+			return;
+		}
+		
+		fibril_mutex_lock(kbd->repeat_mtx);
+
+		if (kbd->repeat.key_new > 0) {
+			if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
+				usb_log_debug2("Repeating key: %u.\n", 
+				    kbd->repeat.key_repeated);
+				// ugly hack with the NULL
+				usb_kbd_push_ev(NULL, kbd, KEY_PRESS, 
+				    kbd->repeat.key_repeated);
+				delay = kbd->repeat.delay_between;
+			} else {
+				usb_log_debug2("New key to repeat: %u.\n",
+				    kbd->repeat.key_new);
+				kbd->repeat.key_repeated = kbd->repeat.key_new;
+				delay = kbd->repeat.delay_before;
+			}
+		} else {
+			if (kbd->repeat.key_repeated > 0) {
+				usb_log_debug2("Stopping to repeat key: %u.\n",
+				    kbd->repeat.key_repeated);
+				kbd->repeat.key_repeated = 0;
+			}
+			delay = CHECK_DELAY;
+		}
+		fibril_mutex_unlock(kbd->repeat_mtx);
+		
+		async_usleep(delay);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Main routine to be executed by a fibril for handling auto-repeat.
+ *
+ * Starts the loop for checking changes in auto-repeat.
+ * 
+ * @param arg User-specified argument. Expects pointer to the keyboard device
+ *            structure representing the keyboard.
+ *
+ * @retval EOK if the routine has finished.
+ * @retval EINVAL if no argument is supplied.
+ */
+int usb_kbd_repeat_fibril(void *arg)
+{
+	usb_log_debug("Autorepeat fibril spawned.\n");
+	
+	if (arg == NULL) {
+		usb_log_error("No device!\n");
+		return EINVAL;
+	}
+	
+	usb_kbd_t *kbd = (usb_kbd_t *)arg;
+	
+	usb_kbd_repeat_loop(kbd);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Start repeating particular key.
+ *
+ * @note Only one key is repeated at any time, so calling this function 
+ *       effectively cancels auto-repeat of the current repeated key (if any)
+ *       and 'schedules' another key for auto-repeat.
+ *
+ * @param kbd Keyboard device structure.
+ * @param key Key to start repeating.
+ */
+void usb_kbd_repeat_start(usb_kbd_t *kbd, unsigned int key)
+{
+	fibril_mutex_lock(kbd->repeat_mtx);
+	kbd->repeat.key_new = key;
+	fibril_mutex_unlock(kbd->repeat_mtx);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Stop repeating particular key.
+ *
+ * @note Only one key is repeated at any time, but this function may be called
+ *       even with key that is not currently repeated (in that case nothing 
+ *       happens).
+ *
+ * @param kbd Keyboard device structure.
+ * @param key Key to stop repeating.
+ */
+void usb_kbd_repeat_stop(usb_kbd_t *kbd, unsigned int key)
+{
+	fibril_mutex_lock(kbd->repeat_mtx);
+	if (key == kbd->repeat.key_new) {
+		kbd->repeat.key_new = 0;
+	}
+	fibril_mutex_unlock(kbd->repeat_mtx);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID keyboard autorepeat facilities
+ */
+
+#ifndef USB_HID_KBDREPEAT_H_
+#define USB_HID_KBDREPEAT_H_
+
+struct usb_kbd_t;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Structure for keeping information needed for auto-repeat of keys.
+ */
+typedef struct {
+	/** Last pressed key. */
+	unsigned int key_new;
+	/** Key to be repeated. */
+	unsigned int key_repeated;
+	/** Delay before first repeat in microseconds. */
+	unsigned int delay_before;
+	/** Delay between repeats in microseconds. */
+	unsigned int delay_between;
+} usb_kbd_repeat_t;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_repeat_fibril(void *arg);
+
+void usb_kbd_repeat_start(struct usb_kbd_t *kbd, unsigned int key);
+
+void usb_kbd_repeat_stop(struct usb_kbd_t *kbd, unsigned int key);
+
+#endif /* USB_HID_KBDREPEAT_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/main.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/kbd/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB KBD driver.
+ */
+
+#include <ddf/driver.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/dev/driver.h>
+
+#include "kbddev.h"
+#include "kbdrepeat.h"
+
+/*----------------------------------------------------------------------------*/
+
+#define NAME "usbkbd"
+
+/**
+ * Function for adding a new device of type USB/HID/keyboard.
+ *
+ * This functions initializes required structures from the device's descriptors
+ * and starts new fibril for polling the keyboard for events and another one for
+ * handling auto-repeat of keys.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ * @note Currently supports only boot-protocol keyboards.
+ *
+ * @param dev Device to add.
+ *
+ * @retval EOK if successful.
+ * @retval ENOMEM if there
+ * @return Other error code inherited from one of functions usb_kbd_init(),
+ *         ddf_fun_bind() and ddf_fun_add_to_class().
+ *
+ * @sa usb_kbd_fibril(), usb_kbd_repeat_fibril()
+ */
+static int usb_kbd_try_add_device(usb_device_t *dev)
+{
+	/* Create the function exposed under /dev/devices. */
+	ddf_fun_t *kbd_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 
+	    "keyboard");
+	if (kbd_fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/* 
+	 * Initialize device (get and process descriptors, get address, etc.)
+	 */
+	usb_log_debug("Initializing USB/HID KBD device...\n");
+	
+	usb_kbd_t *kbd_dev = usb_kbd_new();
+	if (kbd_dev == NULL) {
+		usb_log_error("Error while creating USB/HID KBD device "
+		    "structure.\n");
+		ddf_fun_destroy(kbd_fun);
+		return ENOMEM;  // TODO: some other code??
+	}
+	
+	int rc = usb_kbd_init(kbd_dev, dev);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize USB/HID KBD device.\n");
+		ddf_fun_destroy(kbd_fun);
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}	
+	
+	usb_log_debug("USB/HID KBD device structure initialized.\n");
+	
+	/*
+	 * Store the initialized keyboard device and keyboard ops
+	 * to the DDF function.
+	 */
+	kbd_fun->driver_data = kbd_dev;
+	kbd_fun->ops = &keyboard_ops;
+
+	rc = ddf_fun_bind(kbd_fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(kbd_fun);
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class 'keyboard': %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(kbd_fun);
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	/* Start automated polling function.
+	 * This will create a separate fibril that will query the device
+	 * for the data continuously 
+	 */
+       rc = usb_device_auto_poll(dev,
+	   /* Index of the polling pipe. */
+	   USB_KBD_POLL_EP_NO,
+	   /* Callback when data arrives. */
+	   usb_kbd_polling_callback,
+	   /* How much data to request. */
+	   dev->pipes[USB_KBD_POLL_EP_NO].pipe->max_packet_size,
+	   /* Callback when the polling ends. */
+	   usb_kbd_polling_ended_callback,
+	   /* Custom argument. */
+	   kbd_dev);
+	
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to start polling fibril for `%s'.\n",
+		    dev->ddf_dev->name);
+		return rc;
+	}
+	
+	/*
+	 * Create new fibril for auto-repeat
+	 */
+	fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
+	if (fid == 0) {
+		usb_log_error("Failed to start fibril for KBD auto-repeat");
+		return ENOMEM;
+	}
+	fibril_add_ready(fid);
+
+	(void)keyboard_ops;
+
+	/*
+	 * Hurrah, device is initialized.
+	 */
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Callback for passing a new device to the driver.
+ *
+ * @note Currently, only boot-protocol keyboards are supported by this driver.
+ *
+ * @param dev Structure representing the new device.
+ *
+ * @retval EOK if successful. 
+ * @retval EREFUSED if the device is not supported.
+ */
+static int usb_kbd_add_device(usb_device_t *dev)
+{
+	usb_log_debug("usb_kbd_add_device()\n");
+	
+	if (dev->interface_no < 0) {
+		usb_log_warning("Device is not a supported keyboard.\n");
+		usb_log_error("Failed to add USB KBD device: endpoint not "
+		    "found.\n");
+		return ENOTSUP;
+	}
+	
+	int rc = usb_kbd_try_add_device(dev);
+	
+	if (rc != EOK) {
+		usb_log_warning("Device is not a supported keyboard.\n");
+		usb_log_error("Failed to add KBD device: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_log_info("Keyboard `%s' ready to use.\n", dev->ddf_dev->name);
+
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/* Currently, the framework supports only device adding. Once the framework
+ * supports unplug, more callbacks will be added. */
+static usb_driver_ops_t usb_kbd_driver_ops = {
+        .add_device = usb_kbd_add_device,
+};
+
+
+/* The driver itself. */
+static usb_driver_t usb_kbd_driver = {
+        .name = NAME,
+        .ops = &usb_kbd_driver_ops,
+        .endpoints = usb_kbd_endpoints
+};
+
+/*----------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS USB KBD driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+
+	return usb_driver_main(&usb_kbd_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/main.c
===================================================================
--- uspace/drv/bus/usb/usbhid/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB HID driver.
+ */
+
+#include <ddf/driver.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/dev/driver.h>
+#include <usb/dev/poll.h>
+
+#include "usbhid.h"
+
+/*----------------------------------------------------------------------------*/
+
+#define NAME "usbhid"
+
+/**
+ * Function for adding a new device of type USB/HID/keyboard.
+ *
+ * This functions initializes required structures from the device's descriptors
+ * and starts new fibril for polling the keyboard for events and another one for
+ * handling auto-repeat of keys.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ * @note Currently supports only boot-protocol keyboards.
+ *
+ * @param dev Device to add.
+ *
+ * @retval EOK if successful.
+ * @retval ENOMEM if there
+ * @return Other error code inherited from one of functions usb_kbd_init(),
+ *         ddf_fun_bind() and ddf_fun_add_to_class().
+ */
+static int usb_hid_try_add_device(usb_device_t *dev)
+{
+	assert(dev != NULL);
+	
+	/* 
+	 * Initialize device (get and process descriptors, get address, etc.)
+	 */
+	usb_log_debug("Initializing USB/HID device...\n");
+	
+	usb_hid_dev_t *hid_dev = usb_hid_new();
+	if (hid_dev == NULL) {
+		usb_log_error("Error while creating USB/HID device "
+		    "structure.\n");
+		return ENOMEM;
+	}
+	
+	int rc = usb_hid_init(hid_dev, dev);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize USB/HID device.\n");
+		usb_hid_free(&hid_dev);
+		return rc;
+	}	
+	
+	usb_log_debug("USB/HID device structure initialized.\n");
+	
+	/*
+	 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
+	 *    do nej.
+	 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 
+	 *    vyplnenu strukturu usbhid_iface_t.
+	 * 3) klientska aplikacia - musi si rucne vytvorit telefon
+	 *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 
+	 *    k tej fcii.
+	 *    pouzit usb/classes/hid/iface.h - prvy int je telefon
+	 */
+	
+	/* Start automated polling function.
+	 * This will create a separate fibril that will query the device
+	 * for the data continuously 
+	 */
+       rc = usb_device_auto_poll(dev,
+	   /* Index of the polling pipe. */
+	   hid_dev->poll_pipe_index,
+	   /* Callback when data arrives. */
+	   usb_hid_polling_callback,
+	   /* How much data to request. */
+	   dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
+	   /* Callback when the polling ends. */
+	   usb_hid_polling_ended_callback,
+	   /* Custom argument. */
+	   hid_dev);
+	
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to start polling fibril for `%s'.\n",
+		    dev->ddf_dev->name);
+		return rc;
+	}
+
+	/*
+	 * Hurrah, device is initialized.
+	 */
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Callback for passing a new device to the driver.
+ *
+ * @note Currently, only boot-protocol keyboards are supported by this driver.
+ *
+ * @param dev Structure representing the new device.
+ *
+ * @retval EOK if successful. 
+ * @retval EREFUSED if the device is not supported.
+ */
+static int usb_hid_add_device(usb_device_t *dev)
+{
+	usb_log_debug("usb_hid_add_device()\n");
+	
+	if (dev == NULL) {
+		usb_log_warning("Wrong parameter given for add_device().\n");
+		return EINVAL;
+	}
+	
+	if (dev->interface_no < 0) {
+		usb_log_warning("Device is not a supported HID device.\n");
+		usb_log_error("Failed to add HID device: endpoints not found."
+		    "\n");
+		return ENOTSUP;
+	}
+	
+	int rc = usb_hid_try_add_device(dev);
+	
+	if (rc != EOK) {
+		usb_log_warning("Device is not a supported HID device.\n");
+		usb_log_error("Failed to add HID device: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
+
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/* Currently, the framework supports only device adding. Once the framework
+ * supports unplug, more callbacks will be added. */
+static usb_driver_ops_t usb_hid_driver_ops = {
+        .add_device = usb_hid_add_device,
+};
+
+
+/* The driver itself. */
+static usb_driver_t usb_hid_driver = {
+        .name = NAME,
+        .ops = &usb_hid_driver_ops,
+        .endpoints = usb_hid_endpoints
+};
+
+/*----------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS USB HID driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&usb_hid_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB Mouse driver API.
+ */
+
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/hid.h>
+#include <usb/hid/request.h>
+#include <usb/hid/usages/core.h>
+#include <errno.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <str_error.h>
+#include <ipc/mouseev.h>
+#include <io/console.h>
+
+#include <ipc/kbdev.h>
+#include <io/keycode.h>
+
+#include "mousedev.h"
+#include "../usbhid.h"
+
+/** Number of simulated arrow-key presses for singel wheel step. */
+#define ARROWS_PER_SINGLE_WHEEL 3
+
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
+
+#define NAME "mouse"
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_MOUSE,
+	.flags = 0
+};
+
+const char *HID_MOUSE_FUN_NAME = "mouse";
+const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
+const char *HID_MOUSE_CLASS_NAME = "mouse";
+const char *HID_MOUSE_WHEEL_CLASS_NAME = "keyboard";
+
+/** Default idle rate for mouses. */
+static const uint8_t IDLE_RATE = 0;
+static const size_t USB_MOUSE_BUTTON_COUNT = 3;
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63
+};
+
+static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[
+    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = {
+	0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
+	0x09, 0x02,                    // USAGE (Mouse)
+	0xa1, 0x01,                    // COLLECTION (Application)
+	0x09, 0x01,                    //   USAGE (Pointer)
+	0xa1, 0x00,                    //   COLLECTION (Physical)
+	0x95, 0x03,                    //     REPORT_COUNT (3)
+	0x75, 0x01,                    //     REPORT_SIZE (1)
+	0x05, 0x09,                    //     USAGE_PAGE (Button)
+	0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
+	0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
+	0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
+	0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
+	0x81, 0x02,                    //     INPUT (Data,Var,Abs)
+	0x95, 0x01,                    //     REPORT_COUNT (1)
+	0x75, 0x05,                    //     REPORT_SIZE (5)
+	0x81, 0x01,                    //     INPUT (Cnst)
+	0x75, 0x08,                    //     REPORT_SIZE (8)
+	0x95, 0x02,                    //     REPORT_COUNT (2)
+	0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
+	0x09, 0x30,                    //     USAGE (X)
+	0x09, 0x31,                    //     USAGE (Y)
+	0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
+	0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
+	0x81, 0x06,                    //     INPUT (Data,Var,Rel)
+	0xc0,                          //   END_COLLECTION
+	0xc0                           // END_COLLECTION
+};
+
+/*----------------------------------------------------------------------------*/
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+static void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	
+	usb_mouse_t *mouse_dev = (usb_mouse_t *)fun->driver_data;
+	
+	if (mouse_dev == NULL) {
+		usb_log_debug("default_connection_handler: Missing "
+		    "parameters.\n");
+		async_answer_0(icallid, EINVAL);
+		return;
+	}
+	
+	usb_log_debug("default_connection_handler: fun->name: %s\n",
+	              fun->name);
+	usb_log_debug("default_connection_handler: mouse_phone: %d, wheel "
+	    "phone: %d\n", mouse_dev->mouse_phone, mouse_dev->wheel_phone);
+	
+	int *phone = (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) 
+		     ? &mouse_dev->mouse_phone : &mouse_dev->wheel_phone;
+	
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (*phone != -1) {
+			usb_log_debug("default_connection_handler: Console "
+			    "phone to mouse already set.\n");
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		*phone = callback;
+		usb_log_debug("Console phone to mouse set ok (%d).\n", *phone);
+		async_answer_0(icallid, EOK);
+		return;
+	}
+
+	usb_log_debug("default_connection_handler: Invalid function.\n");
+	async_answer_0(icallid, EINVAL);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static usb_mouse_t *usb_mouse_new(void)
+{
+	usb_mouse_t *mouse = calloc(1, sizeof(usb_mouse_t));
+	if (mouse == NULL) {
+		return NULL;
+	}
+	mouse->mouse_phone = -1;
+	mouse->wheel_phone = -1;
+	
+	return mouse;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_mouse_free(usb_mouse_t **mouse_dev)
+{
+	assert(mouse_dev != NULL && *mouse_dev != NULL);
+	
+	// hangup phone to the console
+	if ((*mouse_dev)->mouse_phone >= 0) {
+		async_obsolete_hangup((*mouse_dev)->mouse_phone);
+	}
+	
+	if ((*mouse_dev)->wheel_phone >= 0) {
+		async_obsolete_hangup((*mouse_dev)->wheel_phone);
+	}
+	
+	free(*mouse_dev);
+	*mouse_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
+{
+	unsigned int key = (wheel > 0) ? KC_UP : KC_DOWN;
+
+	if (mouse_dev->wheel_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, wheel roll discarded.\n");
+		return;
+	}
+	
+	int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
+	int i;
+	
+	for (i = 0; i < count; i++) {
+		/* Send arrow press and release. */
+		usb_log_debug2("Sending key %d to the console\n", key);
+		async_obsolete_msg_4(mouse_dev->wheel_phone, KBDEV_EVENT,
+		    KEY_PRESS, key, 0, 0);
+		async_obsolete_msg_4(mouse_dev->wheel_phone, KBDEV_EVENT,
+		    KEY_RELEASE, key, 0, 0);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report,
+    int32_t usage)
+{
+	int result = 0;
+
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
+	    usage);
+
+	usb_hid_report_path_set_report_id(path, rid);
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    report, NULL, path, USB_HID_PATH_COMPARE_END,
+	    USB_HID_REPORT_TYPE_INPUT);
+
+	if (field != NULL) {
+		result = field->value;
+	}
+
+	usb_hid_report_path_free(path);
+
+	return result;
+}
+
+static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev,
+    usb_mouse_t *mouse_dev)
+{
+	assert(mouse_dev != NULL);
+	
+	if (mouse_dev->mouse_phone < 0) {
+		usb_log_warning(NAME " No console phone.\n");
+		return true;
+	}
+
+	int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
+	    hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
+	int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
+	    hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
+	int wheel = get_mouse_axis_move_value(hid_dev->report_id,
+	    hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
+
+	if ((shift_x != 0) || (shift_y != 0)) {
+		async_obsolete_req_2_0(mouse_dev->mouse_phone,
+		    MOUSEEV_MOVE_EVENT, shift_x, shift_y);
+	}
+
+	if (wheel != 0) {
+		usb_mouse_send_wheel(mouse_dev, wheel);
+	}
+	
+	/*
+	 * Buttons
+	 */
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
+	usb_hid_report_path_set_report_id(path, hid_dev->report_id);
+	
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
+	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    USB_HID_REPORT_TYPE_INPUT);
+
+	while (field != NULL) {
+		usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
+		    field->usage);
+		
+		if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
+		    && field->value != 0) {
+			async_obsolete_req_2_0(mouse_dev->mouse_phone,
+			    MOUSEEV_BUTTON_EVENT, field->usage, 1);
+			mouse_dev->buttons[field->usage - field->usage_minimum]
+			    = field->value;
+		} else if (mouse_dev->buttons[field->usage - field->usage_minimum] != 0
+		    && field->value == 0) {
+			async_obsolete_req_2_0(mouse_dev->mouse_phone,
+			   MOUSEEV_BUTTON_EVENT, field->usage, 0);
+			mouse_dev->buttons[field->usage - field->usage_minimum] =
+			   field->value;
+		}
+		
+		field = usb_hid_report_get_sibling(
+		    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}
+	
+	usb_hid_report_path_free(path);
+
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
+{
+	assert(hid_dev != NULL);
+	assert(mouse != NULL);
+	
+	/* Create the function exposed under /dev/devices. */
+	usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_MOUSE_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	fun->ops = &mouse->ops;
+	fun->driver_data = mouse;
+
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("Adding DDF function to class %s...\n", 
+	    HID_MOUSE_CLASS_NAME);
+	rc = ddf_fun_add_to_class(fun, HID_MOUSE_CLASS_NAME);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class %s: %s.\n",
+		    HID_MOUSE_CLASS_NAME, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	/*
+	 * Special function for acting as keyboard (wheel)
+	 */
+	usb_log_debug("Creating DDF function %s...\n", 
+	              HID_MOUSE_WHEEL_FUN_NAME);
+	fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_MOUSE_WHEEL_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/*
+	 * Store the initialized HID device and HID ops
+	 * to the DDF function.
+	 */
+	fun->ops = &mouse->ops;
+	fun->driver_data = mouse;
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("Adding DDF function to class %s...\n", 
+	    HID_MOUSE_WHEEL_CLASS_NAME);
+	rc = ddf_fun_add_to_class(fun, HID_MOUSE_WHEEL_CLASS_NAME);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class %s: %s.\n",
+		    HID_MOUSE_WHEEL_CLASS_NAME, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
+{
+	usb_log_debug("Initializing HID/Mouse structure...\n");
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	usb_mouse_t *mouse_dev = usb_mouse_new();
+	if (mouse_dev == NULL) {
+		usb_log_error("Error while creating USB/HID Mouse device "
+		    "structure.\n");
+		return ENOMEM;
+	}
+	
+	mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT, 
+	    sizeof(int32_t));
+	
+	if (mouse_dev->buttons == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(mouse_dev);
+		return ENOMEM;
+	}
+	
+	// save the Mouse device structure into the HID device structure
+	*data = mouse_dev;
+	
+	// set handler for incoming calls
+	mouse_dev->ops.default_handler = default_connection_handler;
+	
+	// TODO: how to know if the device supports the request???
+	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, IDLE_RATE);
+	
+	int rc = usb_mouse_create_function(hid_dev, mouse_dev);
+	if (rc != EOK) {
+		usb_mouse_free(&mouse_dev);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
+{
+	if (hid_dev == NULL || data == NULL) {
+		usb_log_error("Missing argument to the mouse polling callback."
+		    "\n");
+		return false;
+	}
+	
+	usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
+		
+	return usb_mouse_process_report(hid_dev, mouse_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
+{
+	if (data != NULL) {
+		usb_mouse_free((usb_mouse_t **)&data);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
+{
+	int rc = usb_hid_parse_report_descriptor(hid_dev->report, 
+	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR, 
+	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to parse boot report descriptor: %s\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
+	
+	if (rc != EOK) {
+		usb_log_warning("Failed to set boot protocol to the device: "
+		    "%s\n", str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB Mouse driver API.
+ */
+
+#ifndef USB_HID_MOUSEDEV_H_
+#define USB_HID_MOUSEDEV_H_
+
+#include <usb/dev/driver.h>
+
+struct usb_hid_dev;
+
+/*----------------------------------------------------------------------------*/
+
+/** Container for USB mouse device. */
+typedef struct {
+	/** IPC phone to console (consumer). */
+	int mouse_phone;
+	int wheel_phone;
+	
+	int32_t *buttons;
+	
+	ddf_dev_ops_t ops;
+} usb_mouse_t;
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description;
+
+const char *HID_MOUSE_FUN_NAME;
+const char *HID_MOUSE_CLASS_NAME;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_init(struct usb_hid_dev *hid_dev, void **data);
+
+bool usb_mouse_polling_callback(struct usb_hid_dev *hid_dev, void *data);
+
+void usb_mouse_deinit(struct usb_hid_dev *hid_dev, void *data);
+
+int usb_mouse_set_boot_protocol(struct usb_hid_dev *hid_dev);
+
+/*----------------------------------------------------------------------------*/
+
+#endif // USB_HID_MOUSEDEV_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/multimedia/keymap.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/keymap.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/multimedia/keymap.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * UUSB multimedia key to keycode mapping.
+ */
+
+#include <io/keycode.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include "keymap.h"
+
+/**
+ * Mapping between USB HID multimedia usages (from HID Usage Tables) and 
+ * corresponding HelenOS key codes.
+ *
+ * Currently only Usages used by Logitech UltraX keyboard are present. All other
+ * should result in 0.
+ */
+static int usb_hid_keymap_consumer[0x29c] = {
+	[0xb5] = 0,       /* Scan Next Track */
+	[0xb6] = 0,       /* Scan Previous Track */
+	[0xb7] = 0,       /* Stop */
+	[0xb8] = 0,       /* Eject */
+	[0xcd] = 0/*KC_F2*/,   /* Play/Pause */
+	[0xe2] = 0/*KC_F3*/,   /* Mute */
+	[0xe9] = 0/*KC_F5*/,   /* Volume Increment */
+	[0xea] = 0/*KC_F4*/,   /* Volume Decrement */
+	[0x183] = 0/*KC_F1*/,      /* AL Consumer Control Configuration */
+	[0x18a] = 0,      /* AL Email Reader */
+	[0x192] = 0,      /* AL Calculator */
+	[0x221] = 0,      /* AC Search */
+	[0x223] = 0/*KC_F6*/,      /* AC Home */
+	[0x224] = 0,      /* AC Back */
+	[0x225] = 0,      /* AC Forward */
+	[0x226] = 0,      /* AC Stop */
+	[0x227] = 0,  /* AC Refresh */
+	[0x22a] = 0   /* AC Bookmarks */
+};
+
+/**
+ * Translates USB HID Usages from the Consumer Page into HelenOS keycodes.
+ *
+ * @param usage USB HID Consumer Page Usage number.
+ * 
+ * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
+ */
+unsigned int usb_multimedia_map_usage(int usage)
+{
+	unsigned int key;
+	int *map = usb_hid_keymap_consumer;
+	size_t map_length = sizeof(usb_hid_keymap_consumer) / sizeof(int);
+
+	if ((usage < 0) || ((size_t)usage >= map_length))
+		return -1;
+
+	/*! @todo What if the usage is not in the table? */
+	key = map[usage];
+	
+	return key;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/multimedia/keymap.h
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/keymap.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/multimedia/keymap.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB multimedia key to keycode mapping.
+ */
+
+#ifndef USB_HID_MULTIMEDIA_KEYMAP_H_
+#define USB_HID_MULTIMEDIA_KEYMAP_H_
+
+unsigned int usb_multimedia_map_usage(int usage);
+
+#endif /* USB_HID_MULTIMEDIA_KEYMAP_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB Keyboard multimedia keys subdriver.
+ */
+
+
+#include "multimedia.h"
+#include "../usbhid.h"
+#include "keymap.h"
+
+#include <usb/hid/hidparser.h>
+#include <usb/debug.h>
+#include <usb/hid/usages/core.h>
+#include <usb/hid/usages/consumer.h>
+
+#include <errno.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <str_error.h>
+
+#include <ipc/kbdev.h>
+#include <io/console.h>
+
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
+
+#define NAME "multimedia-keys"
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Logitech UltraX device type.
+ */
+typedef struct usb_multimedia_t {
+	/** Previously pressed keys (not translated to key codes). */
+	//int32_t *keys_old;
+	/** Currently pressed keys (not translated to key codes). */
+	//int32_t *keys;
+	/** Count of stored keys (i.e. number of keys in the report). */
+	//size_t key_count;	
+	/** IPC phone to the console device (for sending key events). */
+	int console_phone;
+} usb_multimedia_t;
+
+
+/*----------------------------------------------------------------------------*/
+/** 
+ * Default handler for IPC methods not handled by DDF.
+ *
+ * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
+ * assumes the caller is the console and thus it stores IPC phone to it for 
+ * later use by the driver to notify about key events.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+static void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	usb_log_debug(NAME " default_connection_handler()\n");
+	
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	
+	usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
+	
+	if (multim_dev == NULL) {
+		async_answer_0(icallid, EINVAL);
+		return;
+	}
+
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (multim_dev->console_phone != -1) {
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		multim_dev->console_phone = callback;
+		usb_log_debug(NAME " Saved phone to console: %d\n", callback);
+		async_answer_0(icallid, EOK);
+		return;
+	}
+	
+	async_answer_0(icallid, EINVAL);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static ddf_dev_ops_t multimedia_ops = {
+	.default_handler = default_connection_handler
+};
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Processes key events.
+ *
+ * @note This function was copied from AT keyboard driver and modified to suit
+ *       USB keyboard.
+ *
+ * @note Lock keys are not sent to the console, as they are completely handled
+ *       in the driver. It may, however, be required later that the driver
+ *       sends also these keys to application (otherwise it cannot use those
+ *       keys at all).
+ * 
+ * @param hid_dev 
+ * @param lgtch_dev 
+ * @param type Type of the event (press / release). Recognized values: 
+ *             KEY_PRESS, KEY_RELEASE
+ * @param key Key code of the key according to HID Usage Tables.
+ */
+static void usb_multimedia_push_ev(usb_hid_dev_t *hid_dev, 
+    usb_multimedia_t *multim_dev, int type, unsigned int key)
+{
+	assert(hid_dev != NULL);
+	assert(multim_dev != NULL);
+	
+	kbd_event_t ev;
+	
+	ev.type = type;
+	ev.key = key;
+	ev.mods = 0;
+	ev.c = 0;
+
+	usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
+	if (multim_dev->console_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
+	
+	async_obsolete_msg_4(multim_dev->console_phone, KBDEV_EVENT, ev.type, ev.key, 
+	    ev.mods, ev.c);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_multimedia_free(usb_multimedia_t **multim_dev)
+{
+	if (multim_dev == NULL || *multim_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_obsolete_hangup((*multim_dev)->console_phone);
+
+	free(*multim_dev);
+	*multim_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_multimedia_create_function(usb_hid_dev_t *hid_dev, 
+    usb_multimedia_t *multim_dev)
+{
+	/* Create the function exposed under /dev/devices. */
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	fun->ops = &multimedia_ops;
+	fun->driver_data = multim_dev;   // TODO: maybe change to hid_dev->data
+	
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("%s function created (jandle: %" PRIun ").\n",
+	    NAME, fun->handle);
+	
+	rc = ddf_fun_add_to_class(fun, "keyboard");
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class 'keyboard': %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
+{
+	if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
+		return EINVAL; /*! @todo Other return code? */
+	}
+	
+	usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
+	
+	usb_multimedia_t *multim_dev = (usb_multimedia_t *)malloc(
+	    sizeof(usb_multimedia_t));
+	if (multim_dev == NULL) {
+		return ENOMEM;
+	}
+	
+	multim_dev->console_phone = -1;
+	
+	/*! @todo Autorepeat */
+	
+	// save the KBD device structure into the HID device structure
+	*data = multim_dev;
+	
+	usb_log_debug(NAME " HID/multimedia device structure initialized.\n");
+	
+	int rc = usb_multimedia_create_function(hid_dev, multim_dev);
+	if (rc != EOK) {
+		usb_multimedia_free(&multim_dev);
+		return rc;
+	}
+	
+	usb_log_debug(NAME " HID/multimedia structure initialized.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
+{
+	if (hid_dev == NULL) {
+		return;
+	}
+	
+	if (data != NULL) {
+		usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
+		usb_multimedia_free(&multim_dev);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
+{
+	// TODO: checks
+	if (hid_dev == NULL || data == NULL) {
+		return false;
+	}
+
+	usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
+
+	usb_hid_report_path_set_report_id(path, hid_dev->report_id);
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END 
+	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    USB_HID_REPORT_TYPE_INPUT);
+
+	/*! @todo Is this iterating OK if done multiple times? 
+	 *  @todo The parsing is not OK
+	 */
+	while (field != NULL) {
+		if(field->value != 0) {
+			usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
+			    field->value, field->usage);
+			unsigned int key = 
+			    usb_multimedia_map_usage(field->usage);
+			const char *key_str = 
+			    usbhid_multimedia_usage_to_str(field->usage);
+			usb_log_info("Pressed key: %s\n", key_str);
+			usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS, 
+			                       key);
+		}
+		
+		field = usb_hid_report_get_sibling(
+		    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}	
+
+	usb_hid_report_path_free(path);
+	
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.h
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB Keyboard multimedia keys subdriver.
+ */
+
+#ifndef USB_HID_MULTIMEDIA_H_
+#define USB_HID_MULTIMEDIA_H_
+
+#include <usb/dev/driver.h>
+
+struct usb_hid_dev;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data);
+
+void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data);
+
+bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data);
+
+/*----------------------------------------------------------------------------*/
+
+#endif // USB_HID_MULTIMEDIA_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/subdrivers.c
===================================================================
--- uspace/drv/bus/usb/usbhid/subdrivers.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/subdrivers.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID subdriver mappings.
+ */
+
+#include "subdrivers.h"
+#include <usb/hid/usages/core.h>
+#include <usb/hid/hidpath.h>
+
+#include "multimedia/multimedia.h"
+#include "mouse/mousedev.h"
+#include "generic/hiddev.h"
+
+static usb_hid_subdriver_usage_t path_kbd[] = {
+	{USB_HIDUT_PAGE_GENERIC_DESKTOP, 
+	 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD}, 
+	{0, 0}
+};
+
+static usb_hid_subdriver_usage_t path_mouse[] = {
+	{USB_HIDUT_PAGE_GENERIC_DESKTOP, USB_HIDUT_USAGE_GENERIC_DESKTOP_MOUSE},
+	{0, 0}
+};
+
+static usb_hid_subdriver_usage_t multim_key_path[] = {
+	{USB_HIDUT_PAGE_CONSUMER, USB_HIDUT_USAGE_CONSUMER_CONSUMER_CONTROL},
+	{0, 0}
+};
+
+const usb_hid_subdriver_mapping_t usb_hid_subdrivers[] = {
+	{
+		path_kbd,
+		0,
+		USB_HID_PATH_COMPARE_BEGIN,
+		-1,
+		-1,
+		{
+			.init = usb_kbd_init,
+			.deinit = usb_kbd_deinit,
+			.poll = usb_kbd_polling_callback,
+			.poll_end = NULL
+		},
+		
+	},
+	{
+		multim_key_path,
+		1,
+		USB_HID_PATH_COMPARE_BEGIN,
+		-1,
+		-1,
+		{
+			.init = usb_multimedia_init,
+			.deinit = usb_multimedia_deinit,
+			.poll = usb_multimedia_polling_callback,
+			.poll_end = NULL
+		}
+	},
+	{
+		path_mouse,
+		0,
+		USB_HID_PATH_COMPARE_BEGIN,
+		-1,
+		-1,
+		{
+			.init = usb_mouse_init,
+			.deinit = usb_mouse_deinit,
+			.poll = usb_mouse_polling_callback,
+			.poll_end = NULL
+		}
+	},
+	{NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL, NULL}}
+};
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/subdrivers.h
===================================================================
--- uspace/drv/bus/usb/usbhid/subdrivers.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/subdrivers.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID subdriver mappings.
+ */
+
+#ifndef USB_HID_SUBDRIVERS_H_
+#define USB_HID_SUBDRIVERS_H_
+
+#include "usbhid.h"
+#include "kbd/kbddev.h"
+
+/*----------------------------------------------------------------------------*/
+
+typedef struct usb_hid_subdriver_usage {
+	int usage_page;
+	int usage;
+} usb_hid_subdriver_usage_t;
+
+/*----------------------------------------------------------------------------*/
+
+/** Structure representing the mapping between device requirements and the 
+ *  subdriver supposed to handle this device.
+ *
+ * By filling in this structure and adding it to the usb_hid_subdrivers array,
+ * a new subdriver mapping will be created and used by the HID driver when it
+ * searches for appropriate subdrivers for a device.
+ */
+typedef struct usb_hid_subdriver_mapping {
+	/** Usage path that the device's Input reports must contain. 
+	 *
+	 * It is an array of pairs <usage_page, usage>, terminated by a <0, 0>
+	 * pair. If you do not wish to specify the device in this way, set this
+	 * to NULL.
+	 */
+	const usb_hid_subdriver_usage_t *usage_path;
+	
+	/** Report ID for which the path should apply. */
+	int report_id;
+	
+	/** Compare type for the Usage path. */
+	int compare;
+	
+	/** Vendor ID (set to -1 if not specified). */
+	int vendor_id;
+	
+	/** Product ID (set to -1 if not specified). */
+	int product_id;
+	
+	/** Subdriver for controlling this device. */
+	usb_hid_subdriver_t subdriver;
+} usb_hid_subdriver_mapping_t;
+
+/*----------------------------------------------------------------------------*/
+
+extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
+
+/*----------------------------------------------------------------------------*/
+
+#endif /* USB_HID_SUBDRIVERS_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/usbhid.c
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/usbhid.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID driver API.
+ */
+
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/hid.h>
+#include <usb/hid/hidparser.h>
+#include <usb/hid/hidreport.h>
+#include <usb/hid/request.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include "usbhid.h"
+
+#include "kbd/kbddev.h"
+#include "generic/hiddev.h"
+#include "mouse/mousedev.h"
+#include "subdrivers.h"
+
+/*----------------------------------------------------------------------------*/
+
+/* Array of endpoints expected on the device, NULL terminated. */
+usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {
+	&usb_hid_kbd_poll_endpoint_description,
+	&usb_hid_mouse_poll_endpoint_description,
+	&usb_hid_generic_poll_endpoint_description,
+	NULL
+};
+
+static const int USB_HID_MAX_SUBDRIVERS = 10;
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	assert(hid_dev->subdriver_count >= 0);
+	
+	// set the init callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_kbd_init;
+	
+	// set the polling callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
+	    usb_kbd_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_kbd_deinit;
+	
+	// set subdriver count
+	++hid_dev->subdriver_count;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	assert(hid_dev->subdriver_count >= 0);
+	
+	// set the init callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_mouse_init;
+	
+	// set the polling callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
+	    usb_mouse_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_mouse_deinit;
+	
+	// set subdriver count
+	++hid_dev->subdriver_count;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	assert(hid_dev->subdriver_count >= 0);
+	
+	// set the init callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].init =
+	    usb_generic_hid_init;
+	
+	// set the polling callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
+	    usb_generic_hid_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = NULL;
+	
+	// set subdriver count
+	++hid_dev->subdriver_count;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_mapping_t *mapping)
+{
+	assert(hid_dev != NULL);
+	assert(hid_dev->usb_dev != NULL);
+	
+	return (hid_dev->usb_dev->descriptors.device.vendor_id 
+	    == mapping->vendor_id
+	    && hid_dev->usb_dev->descriptors.device.product_id 
+	    == mapping->product_id);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_mapping_t *mapping)
+{
+	assert(hid_dev != NULL);
+	assert(mapping != NULL);
+	
+	usb_hid_report_path_t *usage_path = usb_hid_report_path();
+	if (usage_path == NULL) {
+		usb_log_debug("Failed to create usage path.\n");
+		return false;
+	}
+	int i = 0;
+	while (mapping->usage_path[i].usage != 0 
+	    || mapping->usage_path[i].usage_page != 0) {
+		if (usb_hid_report_path_append_item(usage_path, 
+		    mapping->usage_path[i].usage_page, 
+		    mapping->usage_path[i].usage) != EOK) {
+			usb_log_debug("Failed to append to usage path.\n");
+			usb_hid_report_path_free(usage_path);
+			return false;
+		}
+		++i;
+	}
+	
+	assert(hid_dev->report != NULL);
+	
+	usb_log_debug("Compare flags: %d\n", mapping->compare);
+	
+	bool matches = false;
+	uint8_t report_id = mapping->report_id;
+
+	do {
+		usb_log_debug("Trying report id %u\n", report_id);
+		
+		if (report_id != 0) {
+			usb_hid_report_path_set_report_id(usage_path,
+				report_id);
+		}
+
+		usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+		    hid_dev->report,
+		    NULL, usage_path, mapping->compare, 
+		    USB_HID_REPORT_TYPE_INPUT);
+		
+		usb_log_debug("Field: %p\n", field);
+
+		if (field != NULL) {
+			matches = true;
+			break;
+		}
+		
+		report_id = usb_hid_get_next_report_id(
+		    hid_dev->report, report_id,
+		    USB_HID_REPORT_TYPE_INPUT);
+	} while (!matches && report_id != 0);
+	
+	usb_hid_report_path_free(usage_path);
+	
+	return matches;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_t **subdrivers, int count)
+{
+	int i;
+	
+	if (count <= 0) {
+		hid_dev->subdriver_count = 0;
+		hid_dev->subdrivers = NULL;
+		return EOK;
+	}
+	
+	// add one generic HID subdriver per device
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) * 
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	for (i = 0; i < count; ++i) {
+		hid_dev->subdrivers[i].init = subdrivers[i]->init;
+		hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
+		hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
+		hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
+	}
+	
+	hid_dev->subdrivers[count].init = usb_generic_hid_init;
+	hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback;
+	hid_dev->subdrivers[count].deinit = NULL;
+	hid_dev->subdrivers[count].poll_end = NULL;
+	
+	hid_dev->subdriver_count = count + 1;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL);
+	
+	const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
+	
+	int i = 0, count = 0;
+	const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
+
+	bool ids_matched;
+	bool matched;
+	
+	while (count < USB_HID_MAX_SUBDRIVERS &&
+	    (mapping->usage_path != NULL
+	    || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
+		// check the vendor & product ID
+		if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
+			usb_log_warning("Missing Product ID for Vendor ID %d\n",
+			    mapping->vendor_id);
+			return EINVAL;
+		}
+		if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
+			usb_log_warning("Missing Vendor ID for Product ID %d\n",
+			    mapping->product_id);
+			return EINVAL;
+		}
+		
+		ids_matched = false;
+		matched = false;
+		
+		if (mapping->vendor_id >= 0) {
+			assert(mapping->product_id >= 0);
+			usb_log_debug("Comparing device against vendor ID %u"
+			    " and product ID %u.\n", mapping->vendor_id,
+			    mapping->product_id);
+			if (usb_hid_ids_match(hid_dev, mapping)) {
+				usb_log_debug("IDs matched.\n");
+				ids_matched = true;
+			}
+		}
+		
+		if (mapping->usage_path != NULL) {
+			usb_log_debug("Comparing device against usage path.\n");
+			if (usb_hid_path_matches(hid_dev, mapping)) {
+				// does not matter if IDs were matched
+				matched = true;
+			}
+		} else {
+			// matched only if IDs were matched and there is no path
+			matched = ids_matched;
+		}
+		
+		if (matched) {
+			usb_log_debug("Subdriver matched.\n");
+			subdrivers[count++] = &mapping->subdriver;
+		}
+		
+		mapping = &usb_hid_subdrivers[++i];
+	}
+	
+	// we have all subdrivers determined, save them into the hid device
+	return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
+{
+	assert(hid_dev != NULL && dev != NULL);
+	
+	int rc = EOK;
+	
+	if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
+		usb_log_debug("Found keyboard endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
+	} else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
+		usb_log_debug("Found mouse endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
+	} else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
+		usb_log_debug("Found generic HID endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
+	} else {
+		usb_log_error("None of supported endpoints found - probably"
+		    " not a supported device.\n");
+		rc = ENOTSUP;
+	}
+	
+	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->report != NULL);
+	
+	uint8_t report_id = 0;
+	size_t size;
+	
+	size_t max_size = 0;
+	
+	do {
+		usb_log_debug("Getting size of the report.\n");
+		size = usb_hid_report_byte_size(hid_dev->report, report_id, 
+		    USB_HID_REPORT_TYPE_INPUT);
+		usb_log_debug("Report ID: %u, size: %zu\n", report_id, size);
+		max_size = (size > max_size) ? size : max_size;
+		usb_log_debug("Getting next report ID\n");
+		report_id = usb_hid_get_next_report_id(hid_dev->report, 
+		    report_id, USB_HID_REPORT_TYPE_INPUT);
+	} while (report_id != 0);
+	
+	usb_log_debug("Max size of input report: %zu\n", max_size);
+	
+	hid_dev->max_input_report_size = max_size;
+	assert(hid_dev->input_report == NULL);
+	
+	hid_dev->input_report = malloc(max_size);
+	if (hid_dev->input_report == NULL) {
+		return ENOMEM;
+	}
+	memset(hid_dev->input_report, 0, max_size);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+usb_hid_dev_t *usb_hid_new(void)
+{
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)calloc(1,
+	    sizeof(usb_hid_dev_t));
+	
+	if (hid_dev == NULL) {
+		usb_log_fatal("No memory!\n");
+		return NULL;
+	}
+	
+	hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
+	    usb_hid_report_t)));
+	if (hid_dev->report == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(hid_dev);
+		return NULL;
+	}
+	
+	hid_dev->poll_pipe_index = -1;
+	
+	return hid_dev;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
+{
+	int rc, i;
+	
+	usb_log_debug("Initializing HID structure...\n");
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Failed to init HID structure: no structure given"
+		    ".\n");
+		return EINVAL;
+	}
+	
+	if (dev == NULL) {
+		usb_log_error("Failed to init HID structure: no USB device"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	/* The USB device should already be initialized, save it in structure */
+	hid_dev->usb_dev = dev;
+	
+	rc = usb_hid_check_pipes(hid_dev, dev);
+	if (rc != EOK) {
+		return rc;
+	}
+		
+	/* Get the report descriptor and parse it. */
+	rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 
+	    hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
+	
+	bool fallback = false;
+	
+	if (rc == EOK) {
+		// try to find subdrivers that may want to handle this device
+		rc = usb_hid_find_subdrivers(hid_dev);
+		if (rc != EOK || hid_dev->subdriver_count == 0) {
+			// try to fall back to the boot protocol if available
+			usb_log_info("No subdrivers found to handle this"
+			    " device.\n");
+			fallback = true;
+			assert(hid_dev->subdrivers == NULL);
+			assert(hid_dev->subdriver_count == 0);
+		}
+	} else {
+		usb_log_error("Failed to parse Report descriptor.\n");
+		// try to fall back to the boot protocol if available
+		fallback = true;
+	}
+	
+	if (fallback) {
+		// fall back to boot protocol
+		switch (hid_dev->poll_pipe_index) {
+		case USB_HID_KBD_POLL_EP_NO:
+			usb_log_info("Falling back to kbd boot protocol.\n");
+			rc = usb_kbd_set_boot_protocol(hid_dev);
+			if (rc == EOK) {
+				rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
+			}
+			break;
+		case USB_HID_MOUSE_POLL_EP_NO:
+			usb_log_info("Falling back to mouse boot protocol.\n");
+			rc = usb_mouse_set_boot_protocol(hid_dev);
+			if (rc == EOK) {
+				rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
+			}
+			break;
+		default:
+			assert(hid_dev->poll_pipe_index 
+			    == USB_HID_GENERIC_POLL_EP_NO);
+			
+			usb_log_info("Falling back to generic HID driver.\n");
+			rc = usb_hid_set_generic_hid_subdriver(hid_dev);
+		}
+	}
+	
+	if (rc != EOK) {
+		usb_log_error("No subdriver for handling this device could be"
+		    " initialized: %s.\n", str_error(rc));
+		usb_log_debug("Subdriver count: %d\n", 
+		    hid_dev->subdriver_count);
+		
+	} else {
+		bool ok = false;
+		
+		usb_log_debug("Subdriver count: %d\n", 
+		    hid_dev->subdriver_count);
+		
+		for (i = 0; i < hid_dev->subdriver_count; ++i) {
+			if (hid_dev->subdrivers[i].init != NULL) {
+				usb_log_debug("Initializing subdriver %d.\n",i);
+				rc = hid_dev->subdrivers[i].init(hid_dev,
+				    &hid_dev->subdrivers[i].data);
+				if (rc != EOK) {
+					usb_log_warning("Failed to initialize"
+					    " HID subdriver structure.\n");
+				} else {
+					// at least one subdriver initialized
+					ok = true;
+				}
+			} else {
+				ok = true;
+			}
+		}
+		
+		rc = (ok) ? EOK : -1;	// what error to report
+	}
+	
+	
+	if (rc == EOK) {
+		// save max input report size and allocate space for the report
+		rc = usb_hid_init_report(hid_dev);
+		if (rc != EOK) {
+			usb_log_error("Failed to initialize input report buffer"
+			    ".\n");
+		}
+	}
+	
+	
+	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
+    size_t buffer_size, void *arg)
+{
+	int i;
+	
+	if (dev == NULL || arg == NULL || buffer == NULL) {
+		usb_log_error("Missing arguments to polling callback.\n");
+		return false;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
+	
+	assert(hid_dev->input_report != NULL);
+	usb_log_debug("New data [%zu/%zu]: %s\n", buffer_size,
+	    hid_dev->max_input_report_size,
+	    usb_debug_str_buffer(buffer, buffer_size, 0));
+
+	if (hid_dev->max_input_report_size >= buffer_size) {
+		/*! @todo This should probably be atomic. */
+		memcpy(hid_dev->input_report, buffer, buffer_size);
+		hid_dev->input_report_size = buffer_size;
+		usb_hid_new_report(hid_dev);
+	}
+	
+	// parse the input report
+	
+	int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 
+	    &hid_dev->report_id);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error in usb_hid_parse_report():"
+		    "%s\n", str_error(rc));
+	}	
+	
+	bool cont = false;
+	
+	// continue if at least one of the subdrivers want to continue
+	for (i = 0; i < hid_dev->subdriver_count; ++i) {
+		if (hid_dev->subdrivers[i].poll != NULL
+		    && hid_dev->subdrivers[i].poll(hid_dev, 
+		        hid_dev->subdrivers[i].data)) {
+			cont = true;
+		}
+	}
+	
+	return cont;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, 
+     void *arg)
+{
+	int i; 
+	
+	if (dev == NULL || arg == NULL) {
+		return;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
+	
+	for (i = 0; i < hid_dev->subdriver_count; ++i) {
+		if (hid_dev->subdrivers[i].poll_end != NULL) {
+			hid_dev->subdrivers[i].poll_end(hid_dev,
+			    hid_dev->subdrivers[i].data, reason);
+		}
+	}
+	
+	usb_hid_free(&hid_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_hid_new_report(usb_hid_dev_t *hid_dev)
+{
+	++hid_dev->report_nr;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_hid_report_number(usb_hid_dev_t *hid_dev)
+{
+	return hid_dev->report_nr;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_hid_free(usb_hid_dev_t **hid_dev)
+{
+	int i;
+	
+	if (hid_dev == NULL || *hid_dev == NULL) {
+		return;
+	}
+	
+	usb_log_debug("Subdrivers: %p, subdriver count: %d\n", 
+	    (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count);
+	
+	assert((*hid_dev)->subdrivers != NULL 
+	    || (*hid_dev)->subdriver_count == 0);
+	
+	for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
+		if ((*hid_dev)->subdrivers[i].deinit != NULL) {
+			(*hid_dev)->subdrivers[i].deinit(*hid_dev,
+			    (*hid_dev)->subdrivers[i].data);
+		}
+	}
+	
+	// free the subdrivers info
+	if ((*hid_dev)->subdrivers != NULL) {
+		free((*hid_dev)->subdrivers);
+	}
+
+	// destroy the parser
+	if ((*hid_dev)->report != NULL) {
+		usb_hid_free_report((*hid_dev)->report);
+	}
+
+	if ((*hid_dev)->report_desc != NULL) {
+		free((*hid_dev)->report_desc);
+	}
+
+	free(*hid_dev);
+	*hid_dev = NULL;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/usbhid.h
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/usbhid.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID driver API.
+ */
+
+#ifndef USB_HID_USBHID_H_
+#define USB_HID_USBHID_H_
+
+#include <stdint.h>
+
+#include <usb/hid/hidparser.h>
+#include <ddf/driver.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+#include <usb/hid/hid.h>
+#include <bool.h>
+
+typedef struct usb_hid_dev usb_hid_dev_t;
+typedef struct usb_hid_subdriver usb_hid_subdriver_t;
+
+/** Subdriver initialization callback.
+ *
+ * @param dev Backing USB HID device.
+ * @param data Custom subdriver data (pointer where to store them).
+ * @return Error code.
+ */
+typedef int (*usb_hid_driver_init_t)(usb_hid_dev_t *dev, void **data);
+
+/** Subdriver deinitialization callback.
+ *
+ * @param dev Backing USB HID device.
+ * @param data Custom subdriver data.
+ */
+typedef void (*usb_hid_driver_deinit_t)(usb_hid_dev_t *dev, void *data);
+
+/** Subdriver callback on data from device.
+ *
+ * @param dev Backing USB HID device.
+ * @param data Custom subdriver data.
+ * @return Whether to continue polling (typically true always).
+ */
+typedef bool (*usb_hid_driver_poll_t)(usb_hid_dev_t *dev, void *data);
+
+/** Subdriver callback after communication with the device ceased.
+ *
+ * @param dev Backing USB HID device.
+ * @param data Custom subdriver data.
+ * @param ended_due_to_errors Whether communication ended due to errors in
+ *	communication (true) or deliberately by driver (false).
+ */
+typedef void (*usb_hid_driver_poll_ended_t)(usb_hid_dev_t *dev, void *data,
+    bool ended_due_to_errors);
+
+struct usb_hid_subdriver {
+	/** Function to be called when initializing HID device. */
+	usb_hid_driver_init_t init;
+	/** Function to be called when destroying the HID device structure. */
+	usb_hid_driver_deinit_t deinit;
+	/** Function to be called when data arrives from the device. */
+	usb_hid_driver_poll_t poll;
+	/** Function to be called when polling ends. */
+	usb_hid_driver_poll_ended_t poll_end;
+	/** Arbitrary data needed by the subdriver. */
+	void *data;
+};
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Structure for holding general HID device data.
+ */
+struct usb_hid_dev {
+	/** Structure holding generic USB device information. */
+	usb_device_t *usb_dev;
+	
+	/** Index of the polling pipe in usb_hid_endpoints array. */
+	int poll_pipe_index;
+	
+	/** Subdrivers. */
+	usb_hid_subdriver_t *subdrivers;
+	
+	/** Number of subdrivers. */
+	int subdriver_count;
+	
+	/** Report descriptor. */
+	uint8_t *report_desc;
+
+	/** Report descriptor size. */
+	size_t report_desc_size;
+	
+	/** HID Report parser. */
+	usb_hid_report_t *report;
+	
+	uint8_t report_id;
+	
+	uint8_t *input_report;
+	
+	size_t input_report_size;
+	size_t max_input_report_size;
+	
+	int report_nr;
+};
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	USB_HID_KBD_POLL_EP_NO = 0,
+	USB_HID_MOUSE_POLL_EP_NO = 1,
+	USB_HID_GENERIC_POLL_EP_NO = 2,
+	USB_HID_POLL_EP_COUNT = 3
+};
+
+usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1];
+
+/*----------------------------------------------------------------------------*/
+
+usb_hid_dev_t *usb_hid_new(void);
+
+int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
+
+bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
+    size_t buffer_size, void *arg);
+
+void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, 
+     void *arg);
+
+void usb_hid_new_report(usb_hid_dev_t *hid_dev);
+
+int usb_hid_report_number(usb_hid_dev_t *hid_dev);
+
+void usb_hid_free(usb_hid_dev_t **hid_dev);
+
+#endif /* USB_HID_USBHID_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/usbhid.ma
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhid/usbhid.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,3 @@
+100 usb&interface&class=HID&subclass=0x01&protocol=0x01
+1000 usb&interface&class=HID&subclass=0x01&protocol=0x02
+100 usb&interface&class=HID
Index: uspace/drv/bus/usb/usbhub/Makefile
===================================================================
--- uspace/drv/bus/usb/usbhub/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbhub
+
+SOURCES = \
+	main.c \
+	utils.c \
+	usbhub.c \
+	ports.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbhub/main.c
===================================================================
--- uspace/drv/bus/usb/usbhub/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,96 @@
+/*
+ * 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 drvusbhub
+ * @{
+ */
+
+#include <ddf/driver.h>
+#include <errno.h>
+#include <async.h>
+#include <stdio.h>
+
+#include <usb/dev/driver.h>
+#include <usb/classes/classes.h>
+
+#include "usbhub.h"
+#include "usbhub_private.h"
+
+/** Hub status-change endpoint description.
+ *
+ * For more information see section 11.15.1 of USB 1.1 specification.
+ */
+static usb_endpoint_description_t hub_status_change_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HUB,
+	.interface_subclass = 0,
+	.interface_protocol = 0,
+	.flags = 0
+};
+
+/**
+ * usb hub driver operations
+ *
+ * The most important one is add_device, which is set to usb_hub_add_device.
+ */
+static usb_driver_ops_t usb_hub_driver_ops = {
+	.add_device = usb_hub_add_device
+};
+
+/**
+ * hub endpoints, excluding control endpoint
+ */
+static usb_endpoint_description_t *usb_hub_endpoints[] = {
+	&hub_status_change_endpoint_description,
+	NULL
+};
+
+/**
+ * static usb hub driver information
+ */
+static usb_driver_t usb_hub_driver = {
+	.name = NAME,
+	.ops = &usb_hub_driver_ops,
+	.endpoints = usb_hub_endpoints
+};
+
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS USB hub driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&usb_hub_driver);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/usbhub/port_status.h
===================================================================
--- uspace/drv/bus/usb/usbhub/port_status.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/port_status.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 drvusbhub
+ * @{
+ */
+
+#ifndef HUB_PORT_STATUS_H
+#define	HUB_PORT_STATUS_H
+
+#include <bool.h>
+#include <sys/types.h>
+#include <usb/dev/request.h>
+#include "usbhub_private.h"
+
+/**
+ * structure holding port status and changes flags.
+ * should not be accessed directly, use supplied getter/setter methods.
+ *
+ * For more information refer to table 11-15 in
+ * "Universal Serial Bus Specification Revision 1.1"
+ *
+ */
+typedef uint32_t usb_port_status_t;
+
+/**
+ * structure holding hub status and changes flags.
+ * should not be accessed directly, use supplied getter/setter methods.
+ *
+ * For more information refer to table 11.16.2.5 in
+ * "Universal Serial Bus Specification Revision 1.1"
+ *
+ */
+typedef uint32_t usb_hub_status_t;
+
+/**
+ * set values in request to be it a port status request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_port_status_request(
+    usb_device_request_setup_packet_t *request, uint16_t port) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
+	request->request = USB_HUB_REQUEST_GET_STATUS;
+	request->value = 0;
+	request->length = 4;
+}
+
+/**
+ * set values in request to be it a port status request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_hub_status_request(
+    usb_device_request_setup_packet_t *request) {
+	request->index = 0;
+	request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;
+	request->request = USB_HUB_REQUEST_GET_STATUS;
+	request->value = 0;
+	request->length = 4;
+}
+
+/**
+ * create request for usb hub port status
+ * @param port
+ * @return
+ */
+static inline usb_device_request_setup_packet_t *
+usb_hub_create_port_status_request(uint16_t port) {
+	usb_device_request_setup_packet_t *result =
+	    malloc(sizeof (usb_device_request_setup_packet_t));
+	usb_hub_set_port_status_request(result, port);
+	return result;
+}
+
+/**
+ * set the device request to be a port feature enable request
+ * @param request
+ * @param port
+ * @param feature_selector
+ */
+static inline void usb_hub_set_enable_port_feature_request(
+    usb_device_request_setup_packet_t *request, uint16_t port,
+    uint16_t feature_selector) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = feature_selector;
+	request->length = 0;
+}
+
+/**
+ * set the device request to be a port feature clear request
+ * @param request
+ * @param port
+ * @param feature_selector
+ */
+static inline void usb_hub_set_disable_port_feature_request(
+    usb_device_request_setup_packet_t *request, uint16_t port,
+    uint16_t feature_selector
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
+	request->value = feature_selector;
+	request->length = 0;
+}
+
+/**
+ * set the device request to be a port enable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_enable_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_C_PORT_ENABLE;
+	request->length = 0;
+}
+
+/**
+ * enable specified port
+ * @param port
+ * @return
+ */
+static inline usb_device_request_setup_packet_t *
+usb_hub_create_enable_port_request(uint16_t port) {
+	usb_device_request_setup_packet_t *result =
+	    malloc(sizeof (usb_device_request_setup_packet_t));
+	usb_hub_set_enable_port_request(result, port);
+	return result;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_disable_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_C_PORT_SUSPEND;
+	request->length = 0;
+}
+
+/**
+ * disable specified port
+ * @param port
+ * @return
+ */
+static inline usb_device_request_setup_packet_t *
+usb_hub_create_disable_port_request(uint16_t port) {
+	usb_device_request_setup_packet_t *result =
+	    malloc(sizeof (usb_device_request_setup_packet_t));
+	usb_hub_set_disable_port_request(result, port);
+	return result;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_reset_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_PORT_RESET;
+	request->length = 0;
+}
+
+/**
+ * disable specified port
+ * @param port
+ * @return
+ */
+static inline usb_device_request_setup_packet_t *
+usb_hub_create_reset_port_request(uint16_t port) {
+	usb_device_request_setup_packet_t *result =
+	    malloc(sizeof (usb_device_request_setup_packet_t));
+	usb_hub_set_reset_port_request(result, port);
+	return result;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_power_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_PORT_POWER;
+	request->length = 0;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_unset_power_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
+	request->value = USB_HUB_FEATURE_PORT_POWER;
+	request->length = 0;
+}
+
+/**
+ * get i`th bit of port status
+ * 
+ * @param status
+ * @param idx
+ * @return
+ */
+static inline bool usb_port_is_status(usb_port_status_t status, int idx) {
+	return (status & (1 << idx)) != 0;
+}
+
+/**
+ * set i`th bit of port status
+ * 
+ * @param status
+ * @param idx
+ * @param value
+ */
+static inline void usb_port_status_set_bit(
+    usb_port_status_t * status, int idx, bool value) {
+	(*status) = value ?
+	    ((*status) | (1 << (idx))) :
+	    ((*status)&(~(1 << (idx))));
+}
+
+/**
+ * get i`th bit of hub status
+ * 
+ * @param status
+ * @param idx
+ * @return
+ */
+static inline bool usb_hub_is_status(usb_hub_status_t status, int idx) {
+	return (status & (1 << idx)) != 0;
+}
+
+/**
+ * set i`th bit of hub status
+ * 
+ * @param status
+ * @param idx
+ * @param value
+ */
+static inline void usb_hub_status_set_bit(
+    usb_hub_status_t *status, int idx, bool value) {
+	(*status) = value ?
+	    ((*status) | (1 << (idx))) :
+	    ((*status)&(~(1 << (idx))));
+}
+
+/**
+ * low speed device on the port indicator
+ * 
+ * @param status
+ * @return true if low speed device is attached
+ */
+static inline bool usb_port_low_speed(usb_port_status_t status) {
+	return usb_port_is_status(status, 9);
+}
+
+/**
+ * set low speed device connected bit in port status
+ * 
+ * @param status
+ * @param low_speed value of the bit
+ */
+static inline void usb_port_set_low_speed(usb_port_status_t *status, bool low_speed) {
+	usb_port_status_set_bit(status, 9, low_speed);
+}
+
+//high speed device attached
+
+/**
+ * high speed device on the port indicator
+ *
+ * @param status
+ * @return true if high speed device is on port
+ */
+static inline bool usb_port_high_speed(usb_port_status_t status) {
+	return usb_port_is_status(status, 10);
+}
+
+/**
+ * set high speed device bit in port status
+ *
+ * @param status
+ * @param high_speed value of the bit
+ */
+static inline void usb_port_set_high_speed(usb_port_status_t *status, bool high_speed) {
+	usb_port_status_set_bit(status, 10, high_speed);
+}
+
+/**
+ * speed getter for port status
+ *
+ * @param status
+ * @return speed of usb device (for more see usb specification)
+ */
+static inline usb_speed_t usb_port_speed(usb_port_status_t status) {
+	if (usb_port_low_speed(status))
+		return USB_SPEED_LOW;
+	if (usb_port_high_speed(status))
+		return USB_SPEED_HIGH;
+	return USB_SPEED_FULL;
+}
+
+
+
+#endif	/* HUB_PORT_STATUS_H */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/ports.c
===================================================================
--- uspace/drv/bus/usb/usbhub/ports.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/ports.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,465 @@
+/*
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * Hub ports functions.
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <str_error.h>
+#include <inttypes.h>
+#include <fibril_synch.h>
+
+#include <usb/debug.h>
+
+#include "ports.h"
+#include "usbhub.h"
+#include "usbhub_private.h"
+#include "port_status.h"
+
+/** Information for fibril for device discovery. */
+struct add_device_phase1 {
+	usb_hub_info_t *hub;
+	size_t port;
+	usb_speed_t speed;
+};
+
+/**
+ * count of port status changes that are not explicitly handled by
+ * any function here and must be cleared by hand
+ */
+static const unsigned int non_handled_changes_count = 2;
+
+/**
+ * port status changes that are not explicitly handled by
+ * any function here and must be cleared by hand
+ */
+static const int non_handled_changes[] = {
+	USB_HUB_FEATURE_C_PORT_ENABLE,
+	USB_HUB_FEATURE_C_PORT_SUSPEND
+};
+
+static void usb_hub_removed_device(
+    usb_hub_info_t *hub, uint16_t port);
+
+static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
+    uint16_t port, uint32_t status);
+
+static void usb_hub_port_over_current(usb_hub_info_t *hub,
+    uint16_t port, uint32_t status);
+
+static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
+    usb_port_status_t *status);
+
+static int enable_port_callback(int port_no, void *arg);
+
+static int add_device_phase1_worker_fibril(void *arg);
+
+static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
+    usb_speed_t speed);
+
+/**
+ * Process interrupts on given hub port
+ *
+ * Accepts connection, over current and port reset change.
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
+    uint16_t port) {
+	usb_log_debug("Interrupt at port %zu\n", (size_t) port);
+	//determine type of change
+	//usb_pipe_t *pipe = hub->control_pipe;
+
+	int opResult;
+
+	usb_port_status_t status;
+	opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);
+	if (opResult != EOK) {
+		usb_log_error("Failed to get port %zu status: %s.\n",
+		    (size_t) port, str_error(opResult));
+		return;
+	}
+	//connection change
+	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {
+		bool device_connected = usb_port_is_status(status,
+		    USB_HUB_FEATURE_PORT_CONNECTION);
+		usb_log_debug("Connection change on port %zu: %s.\n",
+		    (size_t) port,
+		    device_connected ? "device attached" : "device removed");
+
+		if (device_connected) {
+			opResult = create_add_device_fibril(hub, port,
+			    usb_port_speed(status));
+			if (opResult != EOK) {
+				usb_log_error(
+				    "Cannot handle change on port %zu: %s.\n",
+				    (size_t) port, str_error(opResult));
+			}
+		} else {
+			usb_hub_removed_device(hub, port);
+		}
+	}
+	//over current
+	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {
+		//check if it was not auto-resolved
+		usb_log_debug("Overcurrent change on port\n");
+		usb_hub_port_over_current(hub, port, status);
+	}
+	//port reset
+	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {
+		usb_hub_port_reset_completed(hub, port, status);
+	}
+	usb_log_debug("Port %d status 0x%08" PRIx32 "\n", (int) port, status);
+
+	usb_port_status_set_bit(
+	    &status, USB_HUB_FEATURE_C_PORT_CONNECTION, false);
+	usb_port_status_set_bit(
+	    &status, USB_HUB_FEATURE_C_PORT_RESET, false);
+	usb_port_status_set_bit(
+	    &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT, false);
+
+	//clearing not yet handled changes	
+	unsigned int feature_idx;
+	for (feature_idx = 0;
+	    feature_idx < non_handled_changes_count;
+	    ++feature_idx) {
+		unsigned int bit_idx = non_handled_changes[feature_idx];
+		if (status & (1 << bit_idx)) {
+			usb_log_info(
+			    "There was not yet handled change on port %d: %d"
+			    ";clearing it\n",
+			    port, bit_idx);
+			int opResult = usb_hub_clear_port_feature(
+			    hub->control_pipe,
+			    port, bit_idx);
+			if (opResult != EOK) {
+				usb_log_warning(
+				    "Could not clear port flag %d: %s\n",
+				    bit_idx, str_error(opResult)
+				    );
+			}
+			usb_port_status_set_bit(
+			    &status, bit_idx, false);
+		}
+	}
+	if (status >> 16) {
+		usb_log_info("There is still some unhandled change %X\n",
+		    status);
+	}
+}
+
+/**
+ * routine called when a device on port has been removed
+ *
+ * If the device on port had default address, it releases default address.
+ * Otherwise does not do anything, because DDF does not allow to remove device
+ * from it`s device tree.
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+static void usb_hub_removed_device(
+    usb_hub_info_t *hub, uint16_t port) {
+
+	int opResult = usb_hub_clear_port_feature(hub->control_pipe,
+	    port, USB_HUB_FEATURE_C_PORT_CONNECTION);
+	if (opResult != EOK) {
+		usb_log_warning("Could not clear port-change-connection flag\n");
+	}
+	/** \TODO remove device from device manager - not yet implemented in
+	 * devide manager
+	 */
+
+	//close address
+
+	usb_hub_port_t *the_port = hub->ports + port;
+
+	fibril_mutex_lock(&hub->port_mutex);
+
+	if (the_port->attached_device.address >= 0) {
+		usb_log_warning("Device unplug on `%s' (port %zu): " \
+		    "not implemented.\n", hub->usb_device->ddf_dev->name,
+		    (size_t) port);
+		the_port->attached_device.address = -1;
+		the_port->attached_device.handle = 0;
+	} else {
+		usb_log_warning("Device removed before being registered.\n");
+
+		/*
+		 * Device was removed before port reset completed.
+		 * We will announce a failed port reset to unblock the
+		 * port reset callback from new device wrapper.
+		 */
+		fibril_mutex_lock(&the_port->reset_mutex);
+		the_port->reset_completed = true;
+		the_port->reset_okay = false;
+		fibril_condvar_broadcast(&the_port->reset_cv);
+		fibril_mutex_unlock(&the_port->reset_mutex);
+	}
+
+	fibril_mutex_unlock(&hub->port_mutex);
+}
+
+/**
+ * Process port reset change
+ *
+ * After this change port should be enabled, unless some problem occured.
+ * This functions triggers second phase of enabling new device.
+ * @param hub
+ * @param port
+ * @param status
+ */
+static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
+    uint16_t port, uint32_t status) {
+	usb_log_debug("Port %zu reset complete.\n", (size_t) port);
+	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {
+		/* Finalize device adding. */
+		usb_hub_port_t *the_port = hub->ports + port;
+		fibril_mutex_lock(&the_port->reset_mutex);
+		the_port->reset_completed = true;
+		the_port->reset_okay = true;
+		fibril_condvar_broadcast(&the_port->reset_cv);
+		fibril_mutex_unlock(&the_port->reset_mutex);
+	} else {
+		usb_log_warning(
+		    "Port %zu reset complete but port not enabled.\n",
+		    (size_t) port);
+	}
+	/* Clear the port reset change. */
+	int rc = usb_hub_clear_port_feature(hub->control_pipe,
+	    port, USB_HUB_FEATURE_C_PORT_RESET);
+	if (rc != EOK) {
+		usb_log_error("Failed to clear port %d reset feature: %s.\n",
+		    port, str_error(rc));
+	}
+}
+
+/**
+ * Process over current condition on port.
+ *
+ * Turn off the power on the port.
+ *
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+static void usb_hub_port_over_current(usb_hub_info_t *hub,
+    uint16_t port, uint32_t status) {
+	int opResult;
+	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)) {
+		opResult = usb_hub_clear_port_feature(hub->control_pipe,
+		    port, USB_HUB_FEATURE_PORT_POWER);
+		if (opResult != EOK) {
+			usb_log_error("Cannot power off port %d; %s\n",
+			    port, str_error(opResult));
+		}
+	} else {
+		opResult = usb_hub_set_port_feature(hub->control_pipe,
+		    port, USB_HUB_FEATURE_PORT_POWER);
+		if (opResult != EOK) {
+			usb_log_error("Cannot power on port %d; %s\n",
+			    port, str_error(opResult));
+		}
+	}
+}
+
+/** Retrieve port status.
+ *
+ * @param[in] ctrl_pipe Control pipe to use.
+ * @param[in] port Port number (starting at 1).
+ * @param[out] status Where to store the port status.
+ * @return Error code.
+ */
+static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
+    usb_port_status_t *status) {
+	size_t recv_size;
+	usb_device_request_setup_packet_t request;
+	usb_port_status_t status_tmp;
+
+	usb_hub_set_port_status_request(&request, port);
+	int rc = usb_pipe_control_read(ctrl_pipe,
+	    &request, sizeof (usb_device_request_setup_packet_t),
+	    &status_tmp, sizeof (status_tmp), &recv_size);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (recv_size != sizeof (status_tmp)) {
+		return ELIMIT;
+	}
+
+	if (status != NULL) {
+		*status = status_tmp;
+	}
+
+	return EOK;
+}
+
+/** Callback for enabling a specific port.
+ *
+ * We wait on a CV until port is reseted.
+ * That is announced via change on interrupt pipe.
+ *
+ * @param port_no Port number (starting at 1).
+ * @param arg Custom argument, points to @c usb_hub_info_t.
+ * @return Error code.
+ */
+static int enable_port_callback(int port_no, void *arg) {
+	usb_hub_info_t *hub = arg;
+	int rc;
+	usb_device_request_setup_packet_t request;
+	usb_hub_port_t *my_port = hub->ports + port_no;
+
+	usb_hub_set_reset_port_request(&request, port_no);
+	rc = usb_pipe_control_write(hub->control_pipe,
+	    &request, sizeof (request), NULL, 0);
+	if (rc != EOK) {
+		usb_log_warning("Port reset failed: %s.\n", str_error(rc));
+		return rc;
+	}
+
+	/*
+	 * Wait until reset completes.
+	 */
+	fibril_mutex_lock(&my_port->reset_mutex);
+	while (!my_port->reset_completed) {
+		fibril_condvar_wait(&my_port->reset_cv, &my_port->reset_mutex);
+	}
+	fibril_mutex_unlock(&my_port->reset_mutex);
+
+	if (my_port->reset_okay) {
+		return EOK;
+	} else {
+		return ESTALL;
+	}
+}
+
+/** Fibril for adding a new device.
+ *
+ * Separate fibril is needed because the port reset completion is announced
+ * via interrupt pipe and thus we cannot block here.
+ *
+ * @param arg Pointer to struct add_device_phase1.
+ * @return 0 Always.
+ */
+static int add_device_phase1_worker_fibril(void *arg) {
+	struct add_device_phase1 *data
+	    = (struct add_device_phase1 *) arg;
+
+	usb_address_t new_address;
+	devman_handle_t child_handle;
+
+	int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
+	    &data->hub->connection, data->speed,
+	    enable_port_callback, (int) data->port, data->hub,
+	    &new_address, &child_handle,
+	    NULL, NULL, NULL);
+
+	if (rc != EOK) {
+		usb_log_error("Failed registering device on port %zu: %s.\n",
+		    data->port, str_error(rc));
+		goto leave;
+	}
+
+	fibril_mutex_lock(&data->hub->port_mutex);
+	data->hub->ports[data->port].attached_device.handle = child_handle;
+	data->hub->ports[data->port].attached_device.address = new_address;
+	fibril_mutex_unlock(&data->hub->port_mutex);
+
+	usb_log_info("Detected new device on `%s' (port %zu), "
+	    "address %d (handle %" PRIun ").\n",
+	    data->hub->usb_device->ddf_dev->name, data->port,
+	    new_address, child_handle);
+
+leave:
+	free(arg);
+
+	fibril_mutex_lock(&data->hub->pending_ops_mutex);
+	assert(data->hub->pending_ops_count > 0);
+	data->hub->pending_ops_count--;
+	fibril_condvar_signal(&data->hub->pending_ops_cv);
+	fibril_mutex_unlock(&data->hub->pending_ops_mutex);
+
+
+	return EOK;
+}
+
+/** Start device adding when connection change is detected.
+ *
+ * This fires a new fibril to complete the device addition.
+ *
+ * @param hub Hub where the change occured.
+ * @param port Port index (starting at 1).
+ * @param speed Speed of the device.
+ * @return Error code.
+ */
+static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
+    usb_speed_t speed) {
+	struct add_device_phase1 *data
+	    = malloc(sizeof (struct add_device_phase1));
+	if (data == NULL) {
+		return ENOMEM;
+	}
+	data->hub = hub;
+	data->port = port;
+	data->speed = speed;
+
+	usb_hub_port_t *the_port = hub->ports + port;
+
+	fibril_mutex_lock(&the_port->reset_mutex);
+	the_port->reset_completed = false;
+	fibril_mutex_unlock(&the_port->reset_mutex);
+
+	int rc = usb_hub_clear_port_feature(hub->control_pipe, port,
+	    USB_HUB_FEATURE_C_PORT_CONNECTION);
+	if (rc != EOK) {
+		free(data);
+		usb_log_warning("Failed to clear port change flag: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
+	if (fibril == 0) {
+		free(data);
+		return ENOMEM;
+	}
+	fibril_mutex_lock(&hub->pending_ops_mutex);
+	hub->pending_ops_count++;
+	fibril_mutex_unlock(&hub->pending_ops_mutex);
+	fibril_add_ready(fibril);
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/ports.h
===================================================================
--- uspace/drv/bus/usb/usbhub/ports.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/ports.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,80 @@
+/*
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * Hub ports related functions.
+ */
+#ifndef DRV_USBHUB_PORTS_H
+#define DRV_USBHUB_PORTS_H
+
+#include <usb/dev/driver.h>
+#include <usb/dev/hub.h>
+
+typedef struct usb_hub_info_t usb_hub_info_t;
+
+/** Information about single port on a hub. */
+typedef struct {
+	/** Mutex needed by CV for checking port reset. */
+	fibril_mutex_t reset_mutex;
+	/** CV for waiting to port reset completion. */
+	fibril_condvar_t reset_cv;
+	/** Whether port reset is completed.
+	 * Guarded by @c reset_mutex.
+	 */
+	bool reset_completed;
+	/** Whether to announce the port reset as successful. */
+	bool reset_okay;
+
+	/** Information about attached device. */
+	usb_hc_attached_device_t attached_device;
+} usb_hub_port_t;
+
+/** Initialize hub port information.
+ *
+ * @param port Port to be initialized.
+ */
+static inline void usb_hub_port_init(usb_hub_port_t *port) {
+	port->attached_device.address = -1;
+	port->attached_device.handle = 0;
+	fibril_mutex_initialize(&port->reset_mutex);
+	fibril_condvar_initialize(&port->reset_cv);
+}
+
+
+void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
+	uint16_t port);
+
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * @brief usb hub main functionality
+ */
+
+#include <ddf/driver.h>
+#include <bool.h>
+#include <errno.h>
+#include <str_error.h>
+#include <inttypes.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/descriptor.h>
+#include <usb/dev/recognise.h>
+#include <usb/dev/request.h>
+#include <usb/classes/hub.h>
+#include <usb/dev/poll.h>
+#include <stdio.h>
+
+#include "usbhub.h"
+#include "usbhub_private.h"
+#include "port_status.h"
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/classes/classes.h>
+
+
+static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev);
+
+static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info);
+
+static int usb_hub_set_configuration(usb_hub_info_t *hub_info);
+
+static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info);
+
+static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
+    usb_hub_status_t status);
+
+static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
+    usb_hub_status_t status);
+
+static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info);
+
+static void usb_hub_polling_terminated_callback(usb_device_t *device,
+    bool was_error, void *data);
+
+
+//*********************************************
+//
+//  hub driver code, initialization
+//
+//*********************************************
+
+/**
+ * Initialize hub device driver fibril
+ *
+ * Creates hub representation and fibril that periodically checks hub`s status.
+ * Hub representation is passed to the fibril.
+ * @param usb_dev generic usb device information
+ * @return error code
+ */
+int usb_hub_add_device(usb_device_t *usb_dev) {
+	if (!usb_dev) return EINVAL;
+	usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev);
+	//create hc connection
+	usb_log_debug("Initializing USB wire abstraction.\n");
+	int opResult = usb_hc_connection_initialize_from_device(
+	    &hub_info->connection,
+	    hub_info->usb_device->ddf_dev);
+	if (opResult != EOK) {
+		usb_log_error("Could not initialize connection to device, "
+		    " %s\n",
+		    str_error(opResult));
+		free(hub_info);
+		return opResult;
+	}
+
+	//set hub configuration
+	opResult = usb_hub_set_configuration(hub_info);
+	if (opResult != EOK) {
+		usb_log_error("Could not set hub configuration, %s\n",
+		    str_error(opResult));
+		free(hub_info);
+		return opResult;
+	}
+	//get port count and create attached_devs
+	opResult = usb_hub_process_hub_specific_info(hub_info);
+	if (opResult != EOK) {
+		usb_log_error("Could process hub specific info, %s\n",
+		    str_error(opResult));
+		free(hub_info);
+		return opResult;
+	}
+
+	usb_log_debug("Creating 'hub' function in DDF.\n");
+	ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
+	    fun_exposed, "hub");
+	assert(hub_fun != NULL);
+	hub_fun->ops = NULL;
+
+	opResult = ddf_fun_bind(hub_fun);
+	assert(opResult == EOK);
+	opResult = ddf_fun_add_to_class(hub_fun, "hub");
+	assert(opResult == EOK);
+
+	opResult = usb_hub_start_hub_fibril(hub_info);
+	if (opResult != EOK)
+		free(hub_info);
+	return opResult;
+}
+
+/** Callback for polling hub for changes.
+ *
+ * @param dev Device where the change occured.
+ * @param change_bitmap Bitmap of changed ports.
+ * @param change_bitmap_size Size of the bitmap in bytes.
+ * @param arg Custom argument, points to @c usb_hub_info_t.
+ * @return Whether to continue polling.
+ */
+bool hub_port_changes_callback(usb_device_t *dev,
+    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
+	usb_log_debug("hub_port_changes_callback\n");
+	usb_hub_info_t *hub = (usb_hub_info_t *) arg;
+
+	/* FIXME: check that we received enough bytes. */
+	if (change_bitmap_size == 0) {
+		goto leave;
+	}
+
+	bool change;
+	change = ((uint8_t*) change_bitmap)[0] & 1;
+	if (change) {
+		usb_hub_process_global_interrupt(hub);
+	}
+
+	size_t port;
+	for (port = 1; port < hub->port_count + 1; port++) {
+		bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
+		if (change) {
+			usb_hub_process_port_interrupt(hub, port);
+		}
+	}
+leave:
+	/* FIXME: proper interval. */
+	async_usleep(1000 * 250);
+
+	return true;
+}
+
+
+//*********************************************
+//
+//  support functions
+//
+//*********************************************
+
+/**
+ * create usb_hub_info_t structure
+ *
+ * Does only basic copying of known information into new structure.
+ * @param usb_dev usb device structure
+ * @return basic usb_hub_info_t structure
+ */
+static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev) {
+	usb_hub_info_t * result = malloc(sizeof (usb_hub_info_t));
+	if (!result) return NULL;
+	result->usb_device = usb_dev;
+	result->status_change_pipe = usb_dev->pipes[0].pipe;
+	result->control_pipe = &usb_dev->ctrl_pipe;
+	result->is_default_address_used = false;
+
+	result->ports = NULL;
+	result->port_count = (size_t) - 1;
+	fibril_mutex_initialize(&result->port_mutex);
+
+	fibril_mutex_initialize(&result->pending_ops_mutex);
+	fibril_condvar_initialize(&result->pending_ops_cv);
+	result->pending_ops_count = 0;
+	return result;
+}
+
+/**
+ * Load hub-specific information into hub_info structure and process if needed
+ *
+ * Particularly read port count and initialize structure holding port
+ * information. If there are non-removable devices, start initializing them.
+ * This function is hub-specific and should be run only after the hub is
+ * configured using usb_hub_set_configuration function.
+ * @param hub_info hub representation
+ * @return error code
+ */
+static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) {
+	// get hub descriptor
+	usb_log_debug("Creating serialized descriptor\n");
+	uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
+	usb_hub_descriptor_t * descriptor;
+	int opResult;
+
+	size_t received_size;
+	opResult = usb_request_get_descriptor(hub_info->control_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
+	    USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
+
+	if (opResult != EOK) {
+		usb_log_error("Failed when receiving hub descriptor, "
+		    "%s\n",
+		    str_error(opResult));
+		free(serialized_descriptor);
+		return opResult;
+	}
+	usb_log_debug2("Deserializing descriptor\n");
+	descriptor = usb_create_deserialized_hub_desriptor(
+	    serialized_descriptor);
+	if (descriptor == NULL) {
+		usb_log_warning("could not deserialize descriptor \n");
+		return ENOMEM;
+	}
+	usb_log_debug("setting port count to %d\n", descriptor->ports_count);
+	hub_info->port_count = descriptor->ports_count;
+	bool is_power_switched =
+	    ((descriptor->hub_characteristics & 1) == 0);
+	bool has_individual_port_powering =
+	    ((descriptor->hub_characteristics & 1) != 0);
+	hub_info->ports = malloc(
+	    sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
+	if (!hub_info->ports) {
+		return ENOMEM;
+	}
+	size_t port;
+	for (port = 0; port < hub_info->port_count + 1; ++port) {
+		usb_hub_port_init(&hub_info->ports[port]);
+	}
+	if (is_power_switched) {
+		usb_log_debug("Hub power switched\n");
+
+		if (!has_individual_port_powering) {
+			//this setting actually makes no difference
+			usb_log_debug("Hub has global powering\n");
+		}
+
+		for (port = 1; port <= hub_info->port_count; ++port) {
+			usb_log_debug("Powering port %zu.\n", port);
+			opResult = usb_hub_set_port_feature(hub_info->control_pipe,
+			    port, USB_HUB_FEATURE_PORT_POWER);
+			if (opResult != EOK) {
+				usb_log_error("Cannot power on port %zu: %s.\n",
+				    port, str_error(opResult));
+			}
+		}
+
+	} else {
+		usb_log_debug("Power not switched, not going to be powered\n");
+	}
+	usb_log_debug2("Freeing data\n");
+	free(descriptor);
+	return EOK;
+}
+
+/**
+ * Set configuration of hub
+ *
+ * Check whether there is at least one configuration and sets the first one.
+ * This function should be run prior to running any hub-specific action.
+ * @param hub_info hub representation
+ * @return error code
+ */
+static int usb_hub_set_configuration(usb_hub_info_t *hub_info) {
+	//device descriptor
+	usb_standard_device_descriptor_t *std_descriptor
+	    = &hub_info->usb_device->descriptors.device;
+	usb_log_debug("Hub has %d configurations\n",
+	    std_descriptor->configuration_count);
+	if (std_descriptor->configuration_count < 1) {
+		usb_log_error("There are no configurations available\n");
+		return EINVAL;
+	}
+
+	usb_standard_configuration_descriptor_t *config_descriptor
+	    = (usb_standard_configuration_descriptor_t *)
+	    hub_info->usb_device->descriptors.configuration;
+
+	/* Set configuration. */
+	int opResult = usb_request_set_configuration(
+	    &hub_info->usb_device->ctrl_pipe,
+	    config_descriptor->configuration_number);
+
+	if (opResult != EOK) {
+		usb_log_error("Failed to set hub configuration: %s.\n",
+		    str_error(opResult));
+		return opResult;
+	}
+	usb_log_debug("\tUsed configuration %d\n",
+	    config_descriptor->configuration_number);
+
+	return EOK;
+}
+
+/**
+ * create and start fibril with hub control loop
+ *
+ * Before the fibril is started, the control pipe and host controller
+ * connection of the hub is open.
+ *
+ * @param hub_info hub representing structure
+ * @return error code
+ */
+static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info) {
+	int rc;
+
+	rc = usb_device_auto_poll(hub_info->usb_device, 0,
+	    hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
+	    usb_hub_polling_terminated_callback, hub_info);
+	if (rc != EOK) {
+		usb_log_error("Failed to create polling fibril: %s.\n",
+		    str_error(rc));
+		free(hub_info);
+		return rc;
+	}
+
+	usb_log_info("Controlling hub `%s' (%zu ports).\n",
+	    hub_info->usb_device->ddf_dev->name, hub_info->port_count);
+	return EOK;
+}
+
+//*********************************************
+//
+//  change handling functions
+//
+//*********************************************
+
+/**
+ * process hub over current change
+ *
+ * This means either to power off the hub or power it on.
+ * @param hub_info hub instance
+ * @param status hub status bitmask
+ * @return error code
+ */
+static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
+    usb_hub_status_t status) {
+	int opResult;
+	if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) {
+		//poweroff all ports
+		unsigned int port;
+		for (port = 1; port <= hub_info->port_count; ++port) {
+			opResult = usb_hub_clear_port_feature(
+			    hub_info->control_pipe, port,
+			    USB_HUB_FEATURE_PORT_POWER);
+			if (opResult != EOK) {
+				usb_log_warning(
+				    "Cannot power off port %d;  %s\n",
+				    port, str_error(opResult));
+			}
+		}
+	} else {
+		//power all ports
+		unsigned int port;
+		for (port = 1; port <= hub_info->port_count; ++port) {
+			opResult = usb_hub_set_port_feature(
+			    hub_info->control_pipe, port,
+			    USB_HUB_FEATURE_PORT_POWER);
+			if (opResult != EOK) {
+				usb_log_warning(
+				    "Cannot power off port %d;  %s\n",
+				    port, str_error(opResult));
+			}
+		}
+	}
+	return opResult;
+}
+
+/**
+ * process hub local power change
+ *
+ * This change is ignored.
+ * @param hub_info hub instance
+ * @param status hub status bitmask
+ * @return error code
+ */
+static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
+    usb_hub_status_t status) {
+	int opResult = EOK;
+	opResult = usb_hub_clear_feature(hub_info->control_pipe,
+	    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
+	if (opResult != EOK) {
+		usb_log_error("Cannnot clear hub power change flag: "
+		    "%s\n",
+		    str_error(opResult));
+	}
+	return opResult;
+}
+
+/**
+ * process hub interrupts
+ *
+ * The change can be either in the over-current condition or
+ * local-power change.
+ * @param hub_info hub instance
+ */
+static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) {
+	usb_log_debug("Global interrupt on a hub\n");
+	usb_pipe_t *pipe = hub_info->control_pipe;
+	int opResult;
+
+	usb_port_status_t status;
+	size_t rcvd_size;
+	usb_device_request_setup_packet_t request;
+	//int opResult;
+	usb_hub_set_hub_status_request(&request);
+	//endpoint 0
+
+	opResult = usb_pipe_control_read(
+	    pipe,
+	    &request, sizeof (usb_device_request_setup_packet_t),
+	    &status, 4, &rcvd_size
+	    );
+	if (opResult != EOK) {
+		usb_log_error("Could not get hub status: %s\n",
+		    str_error(opResult));
+		return;
+	}
+	if (rcvd_size != sizeof (usb_port_status_t)) {
+		usb_log_error("Received status has incorrect size\n");
+		return;
+	}
+	//port reset
+	if (
+	    usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
+		usb_process_hub_over_current(hub_info, status);
+	}
+	if (
+	    usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
+		usb_process_hub_local_power_change(hub_info, status);
+	}
+}
+
+/**
+ * callback called from hub polling fibril when the fibril terminates
+ *
+ * Should perform a cleanup - deletes hub_info.
+ * @param device usb device afected
+ * @param was_error indicates that the fibril is stoped due to an error
+ * @param data pointer to usb_hub_info_t structure
+ */
+static void usb_hub_polling_terminated_callback(usb_device_t *device,
+    bool was_error, void *data) {
+	usb_hub_info_t * hub = data;
+	assert(hub);
+
+	fibril_mutex_lock(&hub->pending_ops_mutex);
+
+	/* The device is dead. However there might be some pending operations
+	 * that we need to wait for.
+	 * One of them is device adding in progress.
+	 * The respective fibril is probably waiting for status change
+	 * in port reset (port enable) callback.
+	 * Such change would never come (otherwise we would not be here).
+	 * Thus, we would flush all pending port resets.
+	 */
+	if (hub->pending_ops_count > 0) {
+		fibril_mutex_lock(&hub->port_mutex);
+		size_t port;
+		for (port = 0; port < hub->port_count; port++) {
+			usb_hub_port_t *the_port = hub->ports + port;
+			fibril_mutex_lock(&the_port->reset_mutex);
+			the_port->reset_completed = true;
+			the_port->reset_okay = false;
+			fibril_condvar_broadcast(&the_port->reset_cv);
+			fibril_mutex_unlock(&the_port->reset_mutex);
+		}
+		fibril_mutex_unlock(&hub->port_mutex);
+	}
+	/* And now wait for them. */
+	while (hub->pending_ops_count > 0) {
+		fibril_condvar_wait(&hub->pending_ops_cv,
+		    &hub->pending_ops_mutex);
+	}
+	fibril_mutex_unlock(&hub->pending_ops_mutex);
+
+	usb_device_destroy(hub->usb_device);
+
+	free(hub->ports);
+	free(hub);
+}
+
+
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/usbhub.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/usbhub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,114 @@
+/*
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * @brief Hub driver.
+ */
+#ifndef DRV_USBHUB_USBHUB_H
+#define DRV_USBHUB_USBHUB_H
+
+#include <ipc/devman.h>
+#include <ddf/driver.h>
+
+#include <usb/dev/hub.h>
+#include <usb/classes/hub.h>
+
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+
+#include <fibril_synch.h>
+
+#define NAME "usbhub"
+
+#include "ports.h"
+
+/** Information about attached hub. */
+struct usb_hub_info_t {
+	/** Number of ports. */
+	size_t port_count;
+
+	/** attached device handles, for each port one */
+	usb_hub_port_t *ports;
+
+	fibril_mutex_t port_mutex;
+
+	/** connection to hcd */
+	usb_hc_connection_t connection;
+
+	/** default address is used indicator
+	 *
+	 * If default address is requested by this device, it cannot
+	 * be requested by the same hub again, otherwise a deadlock will occur.
+	 */
+	bool is_default_address_used;
+
+	/** convenience pointer to status change pipe
+	 *
+	 * Status change pipe is initialized in usb_device structure. This is
+	 * pointer into this structure, so that it does not have to be
+	 * searched again and again for the 'right pipe'.
+	 */
+	usb_pipe_t * status_change_pipe;
+
+	/** convenience pointer to control pipe
+	 *
+	 * Control pipe is initialized in usb_device structure. This is
+	 * pointer into this structure, so that it does not have to be
+	 * searched again and again for the 'right pipe'.
+	 */
+	usb_pipe_t * control_pipe;
+
+	/** generic usb device data*/
+	usb_device_t * usb_device;
+
+	/** Number of pending operations on the mutex to prevent shooting
+	 * ourselves in the foot.
+	 * When the hub is disconnected but we are in the middle of some
+	 * operation, we cannot destroy this structure right away because
+	 * the pending operation might use it.
+	 */
+	size_t pending_ops_count;
+	/** Guard for pending_ops_count. */
+	fibril_mutex_t pending_ops_mutex;
+	/** Condition variable for pending_ops_count. */
+	fibril_condvar_t pending_ops_cv;
+
+};
+
+int usb_hub_add_device(usb_device_t *usb_dev);
+
+bool hub_port_changes_callback(usb_device_t *dev,
+    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/usbhub.ma
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/usbhub.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,2 @@
+10 usb&hub
+10 usb&class=hub
Index: uspace/drv/bus/usb/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * @brief Hub driver private definitions
+ */
+
+#ifndef USBHUB_PRIVATE_H
+#define	USBHUB_PRIVATE_H
+
+#include "usbhub.h"
+
+#include <adt/list.h>
+#include <bool.h>
+#include <ddf/driver.h>
+#include <fibril_synch.h>
+
+#include <usb/classes/hub.h>
+#include <usb/usb.h>
+#include <usb/debug.h>
+#include <usb/dev/request.h>
+
+//************
+//
+// convenience define for malloc
+//
+//************
+
+
+usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
+
+/**
+ * Set the device request to be a get hub descriptor request.
+ * @warning the size is allways set to USB_HUB_MAX_DESCRIPTOR_SIZE
+ * @param request
+ * @param addr
+ */
+static inline void usb_hub_set_descriptor_request(
+    usb_device_request_setup_packet_t * request
+    ) {
+	request->index = 0;
+	request->request_type = USB_HUB_REQ_TYPE_GET_DESCRIPTOR;
+	request->request = USB_HUB_REQUEST_GET_DESCRIPTOR;
+	request->value_high = USB_DESCTYPE_HUB;
+	request->value_low = 0;
+	request->length = USB_HUB_MAX_DESCRIPTOR_SIZE;
+}
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param hc Host controller telephone
+ * @param address Hub address
+ * @param port_index Port
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_clear_port_feature(usb_pipe_t *pipe,
+    int port_index,
+    usb_hub_class_feature_t feature) {
+
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
+		.request = USB_DEVREQ_CLEAR_FEATURE,
+		.length = 0,
+		.index = port_index
+	};
+	clear_request.value = feature;
+	return usb_pipe_control_write(pipe, &clear_request,
+	    sizeof (clear_request), NULL, 0);
+}
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param hc Host controller telephone
+ * @param address Hub address
+ * @param port_index Port
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,
+    int port_index,
+    usb_hub_class_feature_t feature) {
+
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
+		.request = USB_DEVREQ_SET_FEATURE,
+		.length = 0,
+		.index = port_index
+	};
+	clear_request.value = feature;
+	return usb_pipe_control_write(pipe, &clear_request,
+	    sizeof (clear_request), NULL, 0);
+}
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param pipe pipe to hub control endpoint
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_clear_feature(usb_pipe_t *pipe,
+    usb_hub_class_feature_t feature) {
+
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
+		.request = USB_DEVREQ_CLEAR_FEATURE,
+		.length = 0,
+		.index = 0
+	};
+	clear_request.value = feature;
+	return usb_pipe_control_write(pipe, &clear_request,
+	    sizeof (clear_request), NULL, 0);
+}
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param pipe pipe to hub control endpoint
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_set_feature(usb_pipe_t *pipe,
+    usb_hub_class_feature_t feature) {
+
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
+		.request = USB_DEVREQ_SET_FEATURE,
+		.length = 0,
+		.index = 0
+	};
+	clear_request.value = feature;
+	return usb_pipe_control_write(pipe, &clear_request,
+	    sizeof (clear_request), NULL, 0);
+}
+
+
+void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t * descriptor);
+
+void usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor,
+    void * serialized_descriptor);
+
+usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
+    void * serialized_descriptor);
+
+void usb_deserialize_hub_desriptor(void * serialized_descriptor,
+    usb_hub_descriptor_t * descriptor);
+
+
+#endif	/* USBHUB_PRIVATE_H */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/utils.c
===================================================================
--- uspace/drv/bus/usb/usbhub/utils.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbhub/utils.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * @brief various utilities
+ */
+#include <ddf/driver.h>
+#include <bool.h>
+#include <errno.h>
+
+#include <usbhc_iface.h>
+#include <usb/descriptor.h>
+#include <usb/classes/hub.h>
+
+#include "usbhub.h"
+#include "usbhub_private.h"
+#include "port_status.h"
+
+
+size_t USB_HUB_MAX_DESCRIPTOR_SIZE = 71;
+
+//*********************************************
+//
+//  various utils
+//
+//*********************************************
+
+//hub descriptor utils
+
+/**
+ * create uint8_t array with serialized descriptor
+ *
+ * @param descriptor
+ * @return newly created serializd descriptor pointer
+ */
+void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t *descriptor) {
+	//base size
+	size_t size = 7;
+	//variable size according to port count
+	size_t var_size = (descriptor->ports_count + 7) / 8;
+	size += 2 * var_size;
+	uint8_t * result = malloc(size);
+	//size
+	if (result)
+		usb_serialize_hub_descriptor(descriptor, result);
+	return result;
+}
+
+/**
+ * serialize descriptor into given buffer
+ *
+ * The buffer size is not checked.
+ * @param descriptor
+ * @param serialized_descriptor
+ */
+void usb_serialize_hub_descriptor(usb_hub_descriptor_t *descriptor,
+    void * serialized_descriptor) {
+	//base size
+	uint8_t * sdescriptor = serialized_descriptor;
+	size_t size = 7;
+	//variable size according to port count
+	size_t var_size = (descriptor->ports_count + 7) / 8;
+	size += 2 * var_size;
+	//size
+	sdescriptor[0] = size;
+	//descriptor type
+	sdescriptor[1] = USB_DESCTYPE_HUB;
+	sdescriptor[2] = descriptor->ports_count;
+	/// @fixme handling of endianness??
+	sdescriptor[3] = descriptor->hub_characteristics / 256;
+	sdescriptor[4] = descriptor->hub_characteristics % 256;
+	sdescriptor[5] = descriptor->pwr_on_2_good_time;
+	sdescriptor[6] = descriptor->current_requirement;
+
+	size_t i;
+	for (i = 0; i < var_size; ++i) {
+		sdescriptor[7 + i] = descriptor->devices_removable[i];
+	}
+	for (i = 0; i < var_size; ++i) {
+		sdescriptor[7 + var_size + i] = 255;
+	}
+}
+
+/**
+ * create deserialized desriptor structure out of serialized descriptor
+ *
+ * The serialized descriptor must be proper usb hub descriptor,
+ * otherwise an eerror might occur.
+ *
+ * @param sdescriptor serialized descriptor
+ * @return newly created deserialized descriptor pointer
+ */
+usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
+    void *serialized_descriptor) {
+	uint8_t * sdescriptor = serialized_descriptor;
+
+	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
+		usb_log_warning("trying to deserialize wrong descriptor %x\n",
+		    sdescriptor[1]);
+		return NULL;
+	}
+
+	usb_hub_descriptor_t * result = malloc(sizeof (usb_hub_descriptor_t));
+	if (result)
+		usb_deserialize_hub_desriptor(serialized_descriptor, result);
+	return result;
+}
+
+/**
+ * deserialize descriptor into given pointer
+ * 
+ * @param serialized_descriptor
+ * @param descriptor
+ * @return
+ */
+void usb_deserialize_hub_desriptor(
+    void * serialized_descriptor, usb_hub_descriptor_t *descriptor) {
+	uint8_t * sdescriptor = serialized_descriptor;
+	descriptor->ports_count = sdescriptor[2];
+	/// @fixme handling of endianness??
+	descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
+	descriptor->pwr_on_2_good_time = sdescriptor[5];
+	descriptor->current_requirement = sdescriptor[6];
+	size_t var_size = (descriptor->ports_count + 7) / 8;
+	//descriptor->devices_removable = (uint8_t*) malloc(var_size);
+
+	size_t i;
+	for (i = 0; i < var_size; ++i) {
+		descriptor->devices_removable[i] = sdescriptor[7 + i];
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/Makefile
===================================================================
--- uspace/drv/bus/usb/usbmast/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmast/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,48 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbmast
+
+SOURCES = \
+	inquiry.c \
+	main.c \
+	mast.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbmast/cmds.h
===================================================================
--- uspace/drv/bus/usb/usbmast/cmds.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmast/cmds.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,85 @@
+/*
+ * 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 drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage commands.
+ */
+
+#ifndef USB_USBMAST_CMDS_H_
+#define USB_USBMAST_CMDS_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+
+typedef struct {
+	uint32_t dCBWSignature;
+	uint32_t dCBWTag;
+	uint32_t dCBWDataTransferLength;
+	uint8_t bmCBWFlags;
+	uint8_t bCBWLUN;
+	uint8_t bCBWBLength;
+	uint8_t CBWCB[16];
+} __attribute__((packed)) usb_massstor_cbw_t;
+
+typedef struct {
+	uint32_t dCSWSignature;
+	uint32_t dCSWTag;
+	uint32_t dCSWDataResidue;
+	uint8_t dCSWStatus;
+} __attribute__((packed)) usb_massstor_csw_t;
+
+static inline void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw,
+    uint32_t tag, uint32_t transfer_length, usb_direction_t dir,
+    uint8_t lun, uint8_t cmd_len, uint8_t *cmd)
+{
+	cbw->dCBWSignature = uint32_host2usb(0x43425355);
+	cbw->dCBWTag = tag;
+	cbw->dCBWDataTransferLength = transfer_length;
+
+	cbw->bmCBWFlags = 0;
+	if (dir == USB_DIRECTION_IN) {
+		cbw->bmCBWFlags |= (1 << 7);
+	}
+
+	/* Only lowest 4 bits. */
+	cbw->bCBWLUN = lun & 0x0F;
+
+	/* Only lowest 5 bits. */
+	cbw->bCBWBLength = cmd_len & 0x1F;
+
+	memcpy(cbw->CBWCB, cmd, cbw->bCBWBLength);
+}
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/inquiry.c
===================================================================
--- uspace/drv/bus/usb/usbmast/inquiry.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmast/inquiry.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,193 @@
+/*
+ * 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 drvusbmast
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB mass storage driver.
+ */
+#include <usb/dev/driver.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/massstor.h>
+#include <errno.h>
+#include <str_error.h>
+#include <str.h>
+#include <ctype.h>
+#include "cmds.h"
+#include "scsi.h"
+#include "mast.h"
+
+#define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
+#define BITS_GET_MID_MASK(type, bitcount, offset) \
+	((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
+#define BITS_GET(type, number, bitcount, offset) \
+	((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
+
+#define INQUIRY_RESPONSE_LENGTH 36
+
+#define STR_UNKNOWN "<unknown>"
+
+/** String constants for SCSI peripheral device types. */
+static const char *str_peripheral_device_types[] = {
+	"direct-access device",
+	"sequential-access device",
+	"printer device",
+	"processor device",
+	"write-once device",
+	"CDROM device",
+	"scanner device",
+	"optical memory device",
+	"medium changer",
+	"communications device",
+	"graphic arts pre-press device",
+	"graphic arts pre-press device",
+	"storage array controller device",
+	"enclosure services device",
+	"simplified direct-access device",
+	"optical card reader/writer device",
+	"bridging expander",
+	"object-based storage device",
+	"automation driver interface",
+	STR_UNKNOWN, // 0x13
+	STR_UNKNOWN, // 0x14
+	STR_UNKNOWN, // 0x15
+	STR_UNKNOWN, // 0x16
+	STR_UNKNOWN, // 0x17
+	STR_UNKNOWN, // 0x18
+	STR_UNKNOWN, // 0x19
+	STR_UNKNOWN, // 0x1A
+	STR_UNKNOWN, // 0x1B
+	STR_UNKNOWN, // 0x1C
+	STR_UNKNOWN, // 0x1D
+	"well-known logical unit",
+	"uknown or no device state"
+};
+#define str_peripheral_device_types_count \
+	(sizeof(str_peripheral_device_types)/sizeof(str_peripheral_device_types[0]))
+
+/** Get string representation for SCSI peripheral device type.
+ *
+ * See for example here for a list
+ * http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type.
+ *
+ * @param type SCSI peripheral device type code.
+ * @return String representation.
+ */
+const char *usb_str_masstor_scsi_peripheral_device_type(int type)
+{
+	if ((type < 0)
+	    || ((size_t)type >= str_peripheral_device_types_count)) {
+		return STR_UNKNOWN;
+	}
+	return str_peripheral_device_types[type];
+}
+
+/** Trim trailing spaces from a string (rewrite with string terminator).
+ *
+ * @param name String to be trimmed (in-out parameter).
+ */
+static void trim_trailing_spaces(char *name)
+{
+	size_t len = str_length(name);
+	while ((len > 0) && isspace((int) name[len - 1])) {
+		name[len - 1] = 0;
+		len--;
+	}
+}
+
+/** Perform SCSI INQUIRY command on USB mass storage device.
+ *
+ * @param dev USB device.
+ * @param bulk_in_idx Index (in dev->pipes) of bulk in pipe.
+ * @param bulk_out_idx Index of bulk out pipe.
+ * @param inquiry_result Where to store parsed inquiry result.
+ * @return Error code.
+ */
+int usb_massstor_inquiry(usb_device_t *dev,
+    size_t bulk_in_idx, size_t bulk_out_idx,
+    usb_massstor_inquiry_result_t *inquiry_result)
+{
+	scsi_cmd_inquiry_t inquiry = {
+		.op_code = 0x12,
+		.lun_evpd = 0,
+		.page_code = 0,
+		.alloc_length = host2uint16_t_be(INQUIRY_RESPONSE_LENGTH),
+		.ctrl = 0
+	};
+	size_t response_len;
+	uint8_t response[INQUIRY_RESPONSE_LENGTH];
+
+	int rc;
+
+	rc = usb_massstor_data_in(dev, bulk_in_idx, bulk_out_idx,
+	    0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
+	    response, INQUIRY_RESPONSE_LENGTH, &response_len);
+
+	if (rc != EOK) {
+		usb_log_error("Failed to probe device %s using %s: %s.\n",
+		   dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
+		return rc;
+	}
+
+	if (response_len < 8) {
+		usb_log_error("The SCSI response is too short.\n");
+		return ERANGE;
+	}
+
+	/*
+	 * This is an ugly part of the code. We will parse the returned
+	 * data by hand and try to get as many useful data as possible.
+	 */
+	bzero(inquiry_result, sizeof(*inquiry_result));
+
+	/* This shall be returned by all devices. */
+	inquiry_result->peripheral_device_type
+	    = BITS_GET(uint8_t, response[0], 5, 0);
+	inquiry_result->removable = BITS_GET(uint8_t, response[1], 1, 7);
+
+	if (response_len < 32) {
+		return EOK;
+	}
+
+	str_ncpy(inquiry_result->vendor_id, 9,
+	    (const char *) &response[8], 8);
+	trim_trailing_spaces(inquiry_result->vendor_id);
+
+	str_ncpy(inquiry_result->product_and_revision, 12,
+	    (const char *) &response[16], 11);
+	trim_trailing_spaces(inquiry_result->product_and_revision);
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,151 @@
+/*
+ * 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 drvusbmast
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB mass storage driver.
+ */
+#include <usb/dev/driver.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/massstor.h>
+#include <errno.h>
+#include <str_error.h>
+#include "cmds.h"
+#include "scsi.h"
+#include "mast.h"
+
+#define NAME "usbmast"
+
+#define BULK_IN_EP 0
+#define BULK_OUT_EP 1
+
+#define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
+#define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
+
+static usb_endpoint_description_t bulk_in_ep = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_MASS_STORAGE,
+	.interface_subclass = USB_MASSSTOR_SUBCLASS_SCSI,
+	.interface_protocol = USB_MASSSTOR_PROTOCOL_BBB,
+	.flags = 0
+};
+static usb_endpoint_description_t bulk_out_ep = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_MASS_STORAGE,
+	.interface_subclass = USB_MASSSTOR_SUBCLASS_SCSI,
+	.interface_protocol = USB_MASSSTOR_PROTOCOL_BBB,
+	.flags = 0
+};
+
+usb_endpoint_description_t *mast_endpoints[] = {
+	&bulk_in_ep,
+	&bulk_out_ep,
+	NULL
+};
+
+/** Callback when new device is attached and recognized as a mass storage.
+ *
+ * @param dev Representation of a the USB device.
+ * @return Error code.
+ */
+static int usbmast_add_device(usb_device_t *dev)
+{
+	int rc;
+	const char *fun_name = "ctl";
+
+	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
+	    fun_name);
+	if (ctl_fun == NULL) {
+		usb_log_error("Failed to create control function.\n");
+		return ENOMEM;
+	}
+	rc = ddf_fun_bind(ctl_fun);
+	if (rc != EOK) {
+		usb_log_error("Failed to bind control function: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	usb_log_info("Pretending to control mass storage `%s'.\n",
+	    dev->ddf_dev->name);
+	usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
+	    dev->pipes[BULK_IN_EP].pipe->endpoint_no,
+	    (size_t) dev->pipes[BULK_IN_EP].descriptor->max_packet_size);
+	usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
+	    dev->pipes[BULK_OUT_EP].pipe->endpoint_no,
+	    (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
+
+	size_t lun_count = usb_masstor_get_lun_count(dev);
+
+	usb_massstor_inquiry_result_t inquiry;
+	rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry);
+	if (rc != EOK) {
+		usb_log_warning("Failed to inquiry device `%s': %s.\n",
+		    dev->ddf_dev->name, str_error(rc));
+		return EOK;
+	}
+
+	usb_log_info("Mass storage `%s': " \
+	    "`%s' by `%s' is %s (%s), %zu LUN(s).\n",
+	    dev->ddf_dev->name,
+	    inquiry.product_and_revision, inquiry.vendor_id,
+	    usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type),
+	    inquiry.removable ? "removable" : "non-removable",
+	    lun_count);
+
+	return EOK;
+}
+
+/** USB mass storage driver ops. */
+static usb_driver_ops_t usbmast_driver_ops = {
+	.add_device = usbmast_add_device,
+};
+
+/** USB mass storage driver. */
+static usb_driver_t usbmast_driver = {
+	.name = NAME,
+	.ops = &usbmast_driver_ops,
+	.endpoints = mast_endpoints
+};
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&usbmast_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/mast.c
===================================================================
--- uspace/drv/bus/usb/usbmast/mast.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmast/mast.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,222 @@
+/*
+ * 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 drvusbmast
+ * @{
+ */
+/**
+ * @file
+ * Generic functions for USB mass storage (implementation).
+ */
+#include "mast.h"
+#include "cmds.h"
+#include <bool.h>
+#include <errno.h>
+#include <str_error.h>
+#include <usb/debug.h>
+#include <usb/dev/request.h>
+
+bool usb_mast_verbose = true;
+
+#define MASTLOG(format, ...) \
+	do { \
+		if (usb_mast_verbose) { \
+			usb_log_debug("USB cl08: " format, ##__VA_ARGS__); \
+		} \
+	} while (false)
+
+/** Request data from mass storage device.
+ *
+ * @param bulk_in_pipe Bulk in pipe to the device.
+ * @param bulk_out_pipe Bulk out pipe to the device.
+ * @param tag Command block wrapper tag (automatically compared with answer).
+ * @param lun LUN index.
+ * @param cmd SCSI command buffer (in SCSI endianness).
+ * @param cmd_size Length of SCSI command @p cmd in bytes.
+ * @param in_buffer Buffer where to store the answer (CSW is not returned).
+ * @param in_buffer_size Size of the buffer (size of the request to the device).
+ * @param received_size Number of actually received bytes.
+ * @return Error code.
+ */
+int usb_massstor_data_in(usb_device_t *dev,
+    size_t bulk_in_pipe_index, size_t bulk_out_pipe_index,
+    uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
+    void *in_buffer, size_t in_buffer_size, size_t *received_size)
+{
+	int rc;
+	size_t act_size;
+	usb_pipe_t *bulk_in_pipe = dev->pipes[bulk_in_pipe_index].pipe;
+	usb_pipe_t *bulk_out_pipe = dev->pipes[bulk_out_pipe_index].pipe;
+
+	/* Prepare CBW - command block wrapper */
+	usb_massstor_cbw_t cbw;
+	usb_massstor_cbw_prepare(&cbw, tag, in_buffer_size,
+	    USB_DIRECTION_IN, lun, cmd_size, cmd);
+
+	/* First, send the CBW. */
+	rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
+	MASTLOG("CBW '%s' sent: %s.\n",
+	    usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
+	    str_error(rc));
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Try to retrieve the data from the device. */
+	act_size = 0;
+	rc = usb_pipe_read(bulk_in_pipe, in_buffer, in_buffer_size, &act_size);
+	MASTLOG("Received %zuB (%s): %s.\n", act_size,
+	    usb_debug_str_buffer((uint8_t *) in_buffer, act_size, 0),
+	    str_error(rc));
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Read CSW. */
+	usb_massstor_csw_t csw;
+	size_t csw_size;
+	rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
+	MASTLOG("CSW '%s' received (%zuB): %s.\n",
+	    usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
+	    str_error(rc));
+	if (rc != EOK) {
+		return rc;
+	}
+	if (csw_size != sizeof(csw)) {
+		return ERANGE;
+	}
+
+	if (csw.dCSWTag != tag) {
+		return EBADCHECKSUM;
+	}
+
+	/*
+	 * Determine the actual return value from the CSW.
+	 */
+	if (csw.dCSWStatus != 0) {
+		// FIXME: better error code
+		// FIXME: distinguish 0x01 and 0x02
+		return EXDEV;
+	}
+
+	size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
+	if (residue > in_buffer_size) {
+		return ERANGE;
+	}
+	if (act_size != in_buffer_size - residue) {
+		return ERANGE;
+	}
+	if (received_size != NULL) {
+		*received_size = in_buffer_size - residue;
+	}
+
+	return EOK;
+}
+
+/** Perform bulk-only mass storage reset.
+ *
+ * @param dev Device to be reseted.
+ * @return Error code.
+ */
+int usb_massstor_reset(usb_device_t *dev)
+{
+	return usb_control_request_set(&dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
+	    0xFF, 0, dev->interface_no, NULL, 0);
+}
+
+/** Perform complete reset recovery of bulk-only mass storage.
+ *
+ * Notice that no error is reported because if this fails, the error
+ * would reappear on next transaction somehow.
+ *
+ * @param dev Device to be reseted.
+ * @param bulk_in_idx Index of bulk in pipe.
+ * @param bulk_out_idx Index of bulk out pipe.
+ */
+void usb_massstor_reset_recovery(usb_device_t *dev,
+    size_t bulk_in_idx, size_t bulk_out_idx)
+{
+	/* We would ignore errors here because if this fails
+	 * we are doomed anyway and any following transaction would fail.
+	 */
+	usb_massstor_reset(dev);
+	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_in_idx].pipe);
+	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_out_idx].pipe);
+}
+
+/** Get max LUN of a mass storage device.
+ *
+ * @see usb_masstor_get_lun_count
+ *
+ * @warning Error from this command does not necessarily indicate malfunction
+ * of the device. Device does not need to support this request.
+ * You shall rather use usb_masstor_get_lun_count.
+ *
+ * @param dev Mass storage device.
+ * @return Error code of maximum LUN (index, not count).
+ */
+int usb_massstor_get_max_lun(usb_device_t *dev)
+{
+	uint8_t max_lun;
+	size_t data_recv_len;
+	int rc = usb_control_request_get(&dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
+	    0xFE, 0, dev->interface_no, &max_lun, 1, &data_recv_len);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (data_recv_len != 1) {
+		return EEMPTY;
+	}
+	return (int) max_lun;
+}
+
+/** Get number of LUNs supported by mass storage device.
+ *
+ * @warning This function hides any error during the request
+ * (typically that shall not be a problem).
+ *
+ * @param dev Mass storage device.
+ * @return Number of LUNs.
+ */
+size_t usb_masstor_get_lun_count(usb_device_t *dev)
+{
+	int max_lun = usb_massstor_get_max_lun(dev);
+	if (max_lun < 0) {
+		max_lun = 1;
+	} else {
+		max_lun++;
+	}
+
+	return (size_t) max_lun;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/mast.h
===================================================================
--- uspace/drv/bus/usb/usbmast/mast.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmast/mast.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,73 @@
+/*
+ * 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 drvusbmast
+ * @{
+ */
+/** @file
+ * Generic functions for USB mass storage.
+ */
+
+#ifndef USB_USBMAST_MAST_H_
+#define USB_USBMAST_MAST_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+
+/** Result of SCSI INQUIRY command.
+ * This is already parsed structure, not the original buffer returned by
+ * the device.
+ */
+typedef struct {
+	/** SCSI peripheral device type. */
+	int peripheral_device_type;
+	/** Whether the device is removable. */
+	bool removable;
+	/** Vendor ID string. */
+	char vendor_id[9];
+	/** Product ID and product revision string. */
+	char product_and_revision[12];
+} usb_massstor_inquiry_result_t;
+
+int usb_massstor_data_in(usb_device_t *dev, size_t, size_t,
+    uint32_t, uint8_t, void *, size_t, void *, size_t, size_t *);
+int usb_massstor_reset(usb_device_t *);
+void usb_massstor_reset_recovery(usb_device_t *, size_t, size_t);
+int usb_massstor_get_max_lun(usb_device_t *);
+size_t usb_masstor_get_lun_count(usb_device_t *);
+int usb_massstor_inquiry(usb_device_t *, size_t, size_t,
+    usb_massstor_inquiry_result_t *);
+const char *usb_str_masstor_scsi_peripheral_device_type(int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/scsi.h
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmast/scsi.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,54 @@
+/*
+ * 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 drvusbmast
+ * @{
+ */
+/** @file
+ * SCSI related structures.
+ */
+
+#ifndef USB_USBMAST_SCSI_H_
+#define USB_USBMAST_SCSI_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+
+typedef struct {
+	uint8_t op_code;
+	uint8_t lun_evpd;
+	uint8_t page_code;
+	uint16_t alloc_length;
+	uint8_t ctrl;
+} __attribute__((packed)) scsi_cmd_inquiry_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/usbmast.ma
===================================================================
--- uspace/drv/bus/usb/usbmast/usbmast.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmast/usbmast.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+50 usb&interface&class=mass-storage&subclass=0x06&protocol=0x50
Index: uspace/drv/bus/usb/usbmid/Makefile
===================================================================
--- uspace/drv/bus/usb/usbmid/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmid/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbmid
+
+SOURCES = \
+	dump.c \
+	explore.c \
+	main.c \
+	usbmid.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbmid/dump.c
===================================================================
--- uspace/drv/bus/usb/usbmid/dump.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmid/dump.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,120 @@
+/*
+ * 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Dumping and debugging functions.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/dp.h>
+#include <usb/classes/classes.h>
+#include "usbmid.h"
+
+/** Dump found descriptor.
+ *
+ * @param data Descriptor data.
+ * @param depth Nesting depth.
+ */
+static void dump_tree_descriptor(uint8_t *data, size_t depth)
+{
+	if (data == NULL) {
+		return;
+	}
+	int type = (int) *(data + 1);
+	if (type == USB_DESCTYPE_INTERFACE) {
+		usb_standard_interface_descriptor_t *descriptor
+		    = (usb_standard_interface_descriptor_t *) data;
+		usb_log_info("Found interface: %s (0x%02x/0x%02x/0x%02x).\n",
+		    usb_str_class(descriptor->interface_class),
+		    (int) descriptor->interface_class,
+		    (int) descriptor->interface_subclass,
+		    (int) descriptor->interface_protocol);
+	}
+}
+
+/** Dump tree of descriptors.
+ *
+ * @param parser Descriptor parser.
+ * @param data Descriptor parser data.
+ * @param root Pointer to current root.
+ * @param depth Nesting depth.
+ */
+static void dump_tree_internal(usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
+    uint8_t *root, size_t depth)
+{
+	if (root == NULL) {
+		return;
+	}
+	dump_tree_descriptor(root, depth);
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
+	do {
+		dump_tree_internal(parser, data, child, depth + 1);
+		child = usb_dp_get_sibling_descriptor(parser, data, root, child);
+	} while (child != NULL);
+}
+
+/** Dump descriptor tree.
+ *
+ * @param parser Descriptor parser.
+ * @param data Descriptor parser data.
+ */
+static void dump_tree(usb_dp_parser_t *parser, usb_dp_parser_data_t *data)
+{
+	uint8_t *ptr = data->data;
+	dump_tree_internal(parser, data, ptr, 0);
+}
+
+/** Dump given descriptors.
+ *
+ * @param descriptors Descriptors buffer (typically full config descriptor).
+ * @param length Size of @p descriptors buffer in bytes.
+ */
+void usbmid_dump_descriptors(uint8_t *descriptors, size_t length)
+{
+	usb_dp_parser_data_t data = {
+		.data = descriptors,
+		.size = length,
+		.arg = NULL
+	};
+
+	usb_dp_parser_t parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+
+	dump_tree(&parser, &data);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/explore.c
===================================================================
--- uspace/drv/bus/usb/usbmid/explore.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmid/explore.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,208 @@
+/*
+ * 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Exploration of available interfaces in the USB device.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb/classes/classes.h>
+#include <usb/dev/request.h>
+#include <usb/dev/dp.h>
+#include <usb/ddfiface.h>
+#include "usbmid.h"
+
+/** Operations of the device itself. */
+static ddf_dev_ops_t mid_device_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
+};
+
+/** Tell whether given interface is already in the list.
+ *
+ * @param list List of usbmid_interface_t members to be searched.
+ * @param interface_no Interface number caller is looking for.
+ * @return Interface @p interface_no is already present in the list.
+ */
+static bool interface_in_list(list_t *list, int interface_no)
+{
+	list_foreach(*list, l) {
+		usbmid_interface_t *iface
+		    = list_get_instance(l, usbmid_interface_t, link);
+		if (iface->interface_no == interface_no) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/** Create list of interfaces from configuration descriptor.
+ *
+ * @param config_descriptor Configuration descriptor.
+ * @param config_descriptor_size Size of configuration descriptor in bytes.
+ * @param list List where to add the interfaces.
+ */
+static void create_interfaces(uint8_t *config_descriptor,
+    size_t config_descriptor_size, list_t *list)
+{
+	usb_dp_parser_data_t data = {
+		.data = config_descriptor,
+		.size = config_descriptor_size,
+		.arg = NULL
+	};
+
+	usb_dp_parser_t parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+
+	uint8_t *interface_ptr = usb_dp_get_nested_descriptor(&parser, &data,
+	    data.data);
+	if (interface_ptr == NULL) {
+		return;
+	}
+
+	do {
+		if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) {
+			goto next_descriptor;
+		}
+
+		usb_standard_interface_descriptor_t *interface
+		    = (usb_standard_interface_descriptor_t *) interface_ptr;
+
+		/* Skip alternate interfaces. */
+		if (!interface_in_list(list, interface->interface_number)) {
+			usbmid_interface_t *iface
+			    = malloc(sizeof(usbmid_interface_t));
+			if (iface == NULL) {
+				break;
+			}
+			link_initialize(&iface->link);
+			iface->fun = NULL;
+			iface->interface_no = interface->interface_number;
+			iface->interface = interface;
+
+			list_append(&iface->link, list);
+		}
+
+		/* TODO: add the alternatives and create match ids from them
+		 * as well.
+		 */
+
+next_descriptor:
+		interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data,
+		    data.data, interface_ptr);
+
+	} while (interface_ptr != NULL);
+
+}
+
+/** Explore MID device.
+ *
+ * We expect that @p dev is initialized and session on control pipe is
+ * started.
+ *
+ * @param dev Device to be explored.
+ * @return Whether to accept this device from devman.
+ */
+bool usbmid_explore_device(usb_device_t *dev)
+{
+	int rc;
+
+	int dev_class = dev->descriptors.device.device_class;
+	if (dev_class != USB_CLASS_USE_INTERFACE) {
+		usb_log_warning(
+		    "Device class: %d (%s), but expected class 0.\n",
+		    dev_class, usb_str_class(dev_class));
+		usb_log_error("Not multi interface device, refusing.\n");
+		return false;
+	}
+
+	/* Short cuts to save on typing ;-). */
+	uint8_t *config_descriptor_raw = dev->descriptors.configuration;
+	size_t config_descriptor_size = dev->descriptors.configuration_size;
+	usb_standard_configuration_descriptor_t *config_descriptor =
+	    (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
+
+	/* Select the first configuration */
+	rc = usb_request_set_configuration(&dev->ctrl_pipe,
+	    config_descriptor->configuration_number);
+	if (rc != EOK) {
+		usb_log_error("Failed to set device configuration: %s.\n",
+		    str_error(rc));
+		return false;
+	}
+
+	/* Create control function */
+	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
+	if (ctl_fun == NULL) {
+		usb_log_error("Failed to create control function.\n");
+		return false;
+	}
+
+	ctl_fun->ops = &mid_device_ops;
+
+	rc = ddf_fun_bind(ctl_fun);
+	if (rc != EOK) {
+		usb_log_error("Failed to bind control function: %s.\n",
+		    str_error(rc));
+		return false;
+	}
+
+	/* Create interface children. */
+	list_t interface_list;
+	list_initialize(&interface_list);
+	create_interfaces(config_descriptor_raw, config_descriptor_size,
+	    &interface_list);
+
+	list_foreach(interface_list, link) {
+		usbmid_interface_t *iface = list_get_instance(link,
+		    usbmid_interface_t, link);
+
+		usb_log_info("Creating child for interface %d (%s).\n",
+		    (int) iface->interface_no,
+		    usb_str_class(iface->interface->interface_class));
+
+		rc = usbmid_spawn_interface_child(dev, iface,
+		    &dev->descriptors.device, iface->interface);
+		if (rc != EOK) {
+			usb_log_error("Failed to create interface child: %s.\n",
+			    str_error(rc));
+		}
+	}
+
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/main.c
===================================================================
--- uspace/drv/bus/usb/usbmid/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmid/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,91 @@
+/*
+ * 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB multi interface device driver.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/dev/request.h>
+#include <usb/descriptor.h>
+#include <usb/dev/pipes.h>
+
+#include "usbmid.h"
+
+/** Callback when new MID device is attached to the host.
+ *
+ * @param gen_dev Generic DDF device representing the new device.
+ * @return Error code.
+ */
+static int usbmid_add_device(usb_device_t *dev)
+{
+	usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
+
+	usb_pipe_start_long_transfer(&dev->ctrl_pipe);
+
+	bool accept = usbmid_explore_device(dev);
+
+	usb_pipe_end_long_transfer(&dev->ctrl_pipe);
+
+	if (!accept) {
+		return ENOTSUP;
+	}
+
+	return EOK;
+}
+
+/** USB MID driver ops. */
+static usb_driver_ops_t mid_driver_ops = {
+	.add_device = usbmid_add_device,
+};
+
+/** USB MID driver. */
+static usb_driver_t mid_driver = {
+	.name = NAME,
+	.ops = &mid_driver_ops,
+	.endpoints = NULL
+};
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": USB multi interface device driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&mid_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/usbmid.c
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmid/usbmid.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,152 @@
+/*
+ * 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Helper functions.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/dev/pipes.h>
+#include <usb/classes/classes.h>
+#include <usb/dev/recognise.h>
+#include "usbmid.h"
+
+/** Callback for DDF USB interface. */
+static int usb_iface_get_address_impl(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	return usb_iface_get_address_hub_impl(fun, handle, address);
+}
+
+/** Callback for DDF USB interface. */
+static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle,
+    int *iface_no)
+{
+	assert(fun);
+
+	usbmid_interface_t *iface = fun->driver_data;
+	assert(iface);
+
+	if (iface_no != NULL) {
+		*iface_no = iface->interface_no;
+	}
+
+	return EOK;
+}
+
+/** DDF interface of the child - interface function. */
+static usb_iface_t child_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
+	.get_address = usb_iface_get_address_impl,
+	.get_interface = usb_iface_get_interface_impl
+};
+
+/** Operations for children - interface functions. */
+static ddf_dev_ops_t child_device_ops = {
+	.interfaces[USB_DEV_IFACE] = &child_usb_iface
+};
+
+
+/** Spawn new child device from one interface.
+ *
+ * @param parent Parent MID device.
+ * @param iface Interface information.
+ * @param device_descriptor Device descriptor.
+ * @param interface_descriptor Interface descriptor.
+ * @return Error code.
+ */
+int usbmid_spawn_interface_child(usb_device_t *parent,
+    usbmid_interface_t *iface,
+    const usb_standard_device_descriptor_t *device_descriptor,
+    const usb_standard_interface_descriptor_t *interface_descriptor)
+{
+	ddf_fun_t *child = NULL;
+	char *child_name = NULL;
+	int rc;
+
+	/*
+	 * Name is class name followed by interface number.
+	 * The interface number shall provide uniqueness while the
+	 * class name something humanly understandable.
+	 */
+	rc = asprintf(&child_name, "%s%d",
+	    usb_str_class(interface_descriptor->interface_class),
+	    (int) interface_descriptor->interface_number);
+	if (rc < 0) {
+		goto error_leave;
+	}
+
+	/* Create the device. */
+	child = ddf_fun_create(parent->ddf_dev, fun_inner, child_name);
+	if (child == NULL) {
+		rc = ENOMEM;
+		goto error_leave;
+	}
+
+	iface->fun = child;
+
+	child->driver_data = iface;
+	child->ops = &child_device_ops;
+
+	rc = usb_device_create_match_ids_from_interface(device_descriptor,
+	    interface_descriptor,
+	    &child->match_ids);
+	if (rc != EOK) {
+		goto error_leave;
+	}
+
+	rc = ddf_fun_bind(child);
+	if (rc != EOK) {
+		goto error_leave;
+	}
+
+	return EOK;
+
+error_leave:
+	if (child != NULL) {
+		child->name = NULL;
+		/* This takes care of match_id deallocation as well. */
+		ddf_fun_destroy(child);
+	}
+	if (child_name != NULL) {
+		free(child_name);
+	}
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/usbmid.h
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmid/usbmid.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,69 @@
+/*
+ * 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 drvusbmid
+ * @{
+ */
+/** @file
+ * Common definitions.
+ */
+
+#ifndef USBMID_H_
+#define USBMID_H_
+
+#include <adt/list.h>
+#include <ddf/driver.h>
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/debug.h>
+#include <usb/dev/driver.h>
+
+#define NAME "usbmid"
+
+/** Container for single interface in a MID device. */
+typedef struct {
+	/** Function container. */
+	ddf_fun_t *fun;
+	/** Interface descriptor. */
+	usb_standard_interface_descriptor_t *interface;
+	/** Interface number. */
+	int interface_no;
+	/** List link. */
+	link_t link;
+} usbmid_interface_t;
+
+bool usbmid_explore_device(usb_device_t *);
+int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t *,
+    const usb_standard_device_descriptor_t *,
+    const usb_standard_interface_descriptor_t *);
+void usbmid_dump_descriptors(uint8_t *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/usbmid.ma
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmid/usbmid.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+100 usb&mid
Index: uspace/drv/bus/usb/usbmouse/Makefile
===================================================================
--- uspace/drv/bus/usb/usbmouse/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmouse/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,50 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbmouse
+
+SOURCES = \
+	init.c \
+	main.c \
+	mouse.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbmouse/init.c
===================================================================
--- uspace/drv/bus/usb/usbmouse/init.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmouse/init.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,141 @@
+/*
+ * 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Initialization routines for USB mouse driver.
+ */
+
+#include "mouse.h"
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/hid.h>
+#include <usb/dev/request.h>
+#include <usb/hid/request.h>
+#include <errno.h>
+
+/** Mouse polling endpoint description for boot protocol subclass. */
+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_MOUSE,
+	.flags = 0
+};
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param fun     Device function handling the call.
+ * @param icallid Call ID.
+ * @param icall   Call data.
+ *
+ */
+static void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid,
+    ipc_call_t *icall)
+{
+	usb_mouse_t *mouse = (usb_mouse_t *) fun->driver_data;
+	assert(mouse != NULL);
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
+	
+	if (callback) {
+		if (mouse->console_sess == NULL) {
+			mouse->console_sess = callback;
+			async_answer_0(icallid, EOK);
+		} else
+			async_answer_0(icallid, ELIMIT);
+	} else
+		async_answer_0(icallid, EINVAL);
+}
+
+/** Device ops for USB mouse. */
+static ddf_dev_ops_t mouse_ops = {
+	.default_handler = default_connection_handler
+};
+
+/** Create USB mouse device.
+ *
+ * The mouse device is stored into <code>dev-&gt;driver_data</code>.
+ *
+ * @param dev Generic device.
+ * @return Error code.
+ */
+int usb_mouse_create(usb_device_t *dev)
+{
+	usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
+	if (mouse == NULL)
+		return ENOMEM;
+	
+	mouse->dev = dev;
+	mouse->console_sess = NULL;
+	
+	int rc;
+	
+	/* Create DDF function. */
+	mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse");
+	if (mouse->mouse_fun == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+	
+	mouse->mouse_fun->ops = &mouse_ops;
+	
+	rc = ddf_fun_bind(mouse->mouse_fun);
+	if (rc != EOK)
+		goto leave;
+	
+	/* Add the function to mouse class. */
+	rc = ddf_fun_add_to_class(mouse->mouse_fun, "mouse");
+	if (rc != EOK)
+		goto leave;
+	
+	/* Set the boot protocol. */
+	rc = usbhid_req_set_protocol(&dev->ctrl_pipe, dev->interface_no,
+	    USB_HID_PROTOCOL_BOOT);
+	if (rc != EOK)
+		goto leave;
+	
+	/* Everything allright. */
+	dev->driver_data = mouse;
+	mouse->mouse_fun->driver_data = mouse;
+	
+	return EOK;
+	
+leave:
+	free(mouse);
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/main.c
===================================================================
--- uspace/drv/bus/usb/usbmouse/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmouse/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,105 @@
+/*
+ * 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB boot protocol mouse driver.
+ */
+
+#include "mouse.h"
+#include <usb/debug.h>
+#include <usb/dev/poll.h>
+#include <errno.h>
+#include <str_error.h>
+
+#define NAME  "usbmouse"
+
+/** Callback when new mouse device is attached and recognised by DDF.
+ *
+ * @param dev Representation of a generic DDF device.
+ *
+ * @return Error code.
+ *
+ */
+static int usbmouse_add_device(usb_device_t *dev)
+{
+	int rc = usb_mouse_create(dev);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize device driver: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_log_debug("Polling pipe at endpoint %d.\n",
+	    dev->pipes[0].pipe->endpoint_no);
+	
+	rc = usb_device_auto_poll(dev, 0, usb_mouse_polling_callback,
+	    dev->pipes[0].pipe->max_packet_size,
+	    usb_mouse_polling_ended_callback, dev->driver_data);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to start polling fibril: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_log_info("controlling new mouse (handle %" PRIun ").\n",
+	    dev->ddf_dev->handle);
+	
+	return EOK;
+}
+
+/** USB mouse driver ops. */
+static usb_driver_ops_t mouse_driver_ops = {
+	.add_device = usbmouse_add_device,
+};
+
+static usb_endpoint_description_t *endpoints[] = {
+	&poll_endpoint_description,
+	NULL
+};
+
+/** USB mouse driver. */
+static usb_driver_t mouse_driver = {
+	.name = NAME,
+	.ops = &mouse_driver_ops,
+	.endpoints = endpoints
+};
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	return usb_driver_main(&mouse_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/mouse.c
===================================================================
--- uspace/drv/bus/usb/usbmouse/mouse.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmouse/mouse.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,131 @@
+/*
+ * 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Actual handling of USB mouse protocol.
+ */
+
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ipc/mouseev.h>
+#include <async.h>
+#include "mouse.h"
+
+/** Mouse polling callback.
+ *
+ * @param dev    Device that is being polled.
+ * @param buffer Data buffer.
+ * @param size   Buffer size in bytes.
+ * @param arg    Pointer to usb_mouse_t.
+ *
+ * @return Always true.
+ *
+ */
+bool usb_mouse_polling_callback(usb_device_t *dev, uint8_t *buffer,
+    size_t size, void *arg)
+{
+	usb_mouse_t *mouse = (usb_mouse_t *) arg;
+	
+	usb_log_debug2("got buffer: %s.\n",
+	    usb_debug_str_buffer(buffer, size, 0));
+	
+	uint8_t butt = buffer[0];
+	char str_buttons[4] = {
+		butt & 1 ? '#' : '.',
+		butt & 2 ? '#' : '.',
+		butt & 4 ? '#' : '.',
+		0
+	};
+	
+	int shift_x = ((int) buffer[1]) - 127;
+	int shift_y = ((int) buffer[2]) - 127;
+	int wheel = ((int) buffer[3]) - 127;
+	
+	if (buffer[1] == 0)
+		shift_x = 0;
+	
+	if (buffer[2] == 0)
+		shift_y = 0;
+	
+	if (buffer[3] == 0)
+		wheel = 0;
+	
+	if (mouse->console_sess) {
+		if ((shift_x != 0) || (shift_y != 0)) {
+			// FIXME: guessed for QEMU
+			
+			async_exch_t *exch = async_exchange_begin(mouse->console_sess);
+			async_req_2_0(exch, MOUSEEV_MOVE_EVENT, -shift_x / 10, -shift_y / 10);
+			async_exchange_end(exch);
+		}
+		if (butt) {
+			// FIXME: proper button clicking
+			
+			async_exch_t *exch = async_exchange_begin(mouse->console_sess);
+			async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, 1, 1);
+			async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, 1, 0);
+			async_exchange_end(exch);
+		}
+	}
+	
+	usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
+	    str_buttons, shift_x, shift_y, wheel);
+	
+	/* Guess. */
+	async_usleep(1000);
+	
+	return true;
+}
+
+/** Callback when polling is terminated.
+ *
+ * @param dev              Device where the polling terminated.
+ * @param recurring_errors Whether the polling was terminated due to
+ *                         recurring errors.
+ * @param arg              Pointer to usb_mouse_t.
+ *
+ */
+void usb_mouse_polling_ended_callback(usb_device_t *dev, bool recurring_errors,
+    void *arg)
+{
+	usb_mouse_t *mouse = (usb_mouse_t *) arg;
+	
+	async_hangup(mouse->console_sess);
+	mouse->console_sess = NULL;
+	
+	usb_device_destroy(dev);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/mouse.h
===================================================================
--- uspace/drv/bus/usb/usbmouse/mouse.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmouse/mouse.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,74 @@
+/*
+ * 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Common definitions for USB mouse driver.
+ */
+
+#ifndef USBMOUSE_MOUSE_H_
+#define USBMOUSE_MOUSE_H_
+
+#include <usb/dev/driver.h>
+#include <usb/dev/pipes.h>
+#include <time.h>
+#include <async.h>
+
+#define POLL_PIPE(dev) \
+	((dev)->pipes[0].pipe)
+
+/** Container for USB mouse device. */
+typedef struct {
+	/** Generic device container. */
+	usb_device_t *dev;
+	
+	/** Function representing the device. */
+	ddf_fun_t *mouse_fun;
+	
+	/** Polling interval in microseconds. */
+	suseconds_t poll_interval_us;
+	
+	/** Callback session to console (consumer). */
+	async_sess_t *console_sess;
+} usb_mouse_t;
+
+extern usb_endpoint_description_t poll_endpoint_description;
+
+extern int usb_mouse_create(usb_device_t *);
+extern bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t,
+    void *);
+extern void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/usbmouse.ma
===================================================================
--- uspace/drv/bus/usb/usbmouse/usbmouse.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/usbmouse/usbmouse.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+100 usb&interface&class=HID&subclass=0x01&protocol=0x02
Index: uspace/drv/bus/usb/vhc/Makefile
===================================================================
--- uspace/drv/bus/usb/vhc/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,57 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBUSBVIRT_PREFIX)/libusbvirt.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSBVIRT_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+BINARY = vhc
+
+SOURCES = \
+	hub/virthub.c \
+	hub/hub.c \
+	hub/virthubops.c \
+	conndev.c \
+	connhost.c \
+	devconn.c \
+	hub.c \
+	main.c \
+	transfer.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/vhc/conn.h
===================================================================
--- uspace/drv/bus/usb/vhc/conn.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/conn.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,54 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Connection handling of incoming calls.
+ */
+#ifndef VHCD_CONN_H_
+#define VHCD_CONN_H_
+
+#include <usb/usb.h>
+#include <usbhc_iface.h>
+#include <usb_iface.h>
+#include "vhcd.h"
+
+extern usbhc_iface_t vhc_iface;
+extern usb_iface_t vhc_usb_iface;
+extern usb_iface_t rh_usb_iface;
+
+void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+void on_client_close(ddf_fun_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/conndev.c
===================================================================
--- uspace/drv/bus/usb/vhc/conndev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/conndev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,139 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * Connection handling of calls from virtual device (implementation).
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <ddf/driver.h>
+#include <usbvirt/ipc.h>
+#include <async.h>
+#include "conn.h"
+
+static fibril_local uintptr_t plugged_device_handle = 0;
+#define PLUGGED_DEVICE_NAME_MAXLEN 256
+static fibril_local char plugged_device_name[PLUGGED_DEVICE_NAME_MAXLEN + 1] = "<unknown>";
+
+/** Receive device name.
+ *
+ * @warning Errors are silently ignored.
+ *
+ * @param sess Session to the virtual device.
+ *
+ */
+static void receive_device_name(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	aid_t opening_request = async_send_0(exch, IPC_M_USBVIRT_GET_NAME, NULL);
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		return;
+	}
+	
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(exch, plugged_device_name,
+	     PLUGGED_DEVICE_NAME_MAXLEN, &data_request_call);
+	
+	async_exchange_end(exch);
+	
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return;
+	}
+	
+	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) || (opening_request_rc != EOK))
+		return;
+	
+	size_t len = IPC_GET_ARG2(data_request_call);
+	plugged_device_name[len] = 0;
+}
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param fun Device handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid,
+    ipc_call_t *icall)
+{
+	vhc_data_t *vhc = fun->dev->driver_data;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
+	
+	if (callback) {
+		int rc = vhc_virtdev_plug(vhc, callback, &plugged_device_handle);
+		if (rc != EOK) {
+			async_answer_0(icallid, rc);
+			async_hangup(callback);
+			return;
+		}
+		
+		async_answer_0(icallid, EOK);
+		
+		receive_device_name(callback);
+		
+		usb_log_info("New virtual device `%s' (id: %" PRIxn ").\n",
+		    plugged_device_name, plugged_device_handle);
+	} else
+		async_answer_0(icallid, EINVAL);
+}
+
+/** Callback when client disconnects.
+ *
+ * Used to unplug virtual USB device.
+ *
+ * @param fun
+ */
+void on_client_close(ddf_fun_t *fun)
+{
+	vhc_data_t *vhc = fun->dev->driver_data;
+
+	if (plugged_device_handle != 0) {
+		usb_log_info("Virtual device `%s' disconnected (id: %" PRIxn ").\n",
+		    plugged_device_name, plugged_device_handle);
+		vhc_virtdev_unplug(vhc, plugged_device_handle);
+	}
+}
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/connhost.c
===================================================================
--- uspace/drv/bus/usb/vhc/connhost.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/connhost.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,490 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * Host controller interface implementation.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+#include <usbhc_iface.h>
+#include "vhcd.h"
+
+#define GET_VHC_DATA(fun) \
+	((vhc_data_t *)fun->dev->driver_data)
+#define VHC_DATA(vhc, fun) \
+	vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef)
+
+#define UNSUPPORTED(methodname) \
+	usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
+	    methodname, __FILE__, __LINE__)
+
+/** Found free USB address.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] speed Speed of the device that will get this address.
+ * @param[out] address Non-null pointer where to store the free address.
+ * @return Error code.
+ */
+static int request_address(ddf_fun_t *fun, usb_speed_t speed,
+    usb_address_t *address)
+{
+	VHC_DATA(vhc, fun);
+
+	usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper,
+	    USB_SPEED_HIGH);
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+
+/** Bind USB address with device devman handle.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] handle Devman handle of the device.
+ * @return Error code.
+ */
+static int bind_address(ddf_fun_t *fun,
+    usb_address_t address, devman_handle_t handle)
+{
+	VHC_DATA(vhc, fun);
+	usb_log_debug("Binding handle %" PRIun " to address %d.\n",
+	    handle, address);
+	usb_device_keeper_bind(&vhc->dev_keeper, address, handle);
+
+	return EOK;
+}
+
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	VHC_DATA(vhc, fun);
+	bool found =
+	    usb_device_keeper_find_by_address(&vhc->dev_keeper, address, handle);
+	return found ? EOK : ENOENT;
+}
+
+/** Release previously requested address.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	VHC_DATA(vhc, fun);
+	usb_log_debug("Releasing address %d...\n", address);
+	usb_device_keeper_release(&vhc->dev_keeper, address);
+
+	return ENOTSUP;
+}
+
+/** Register endpoint for bandwidth reservation.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] speed Endpoint speed (invalid means to use device one).
+ * @param[in] endpoint Endpoint number.
+ * @param[in] transfer_type USB transfer type.
+ * @param[in] direction Endpoint data direction.
+ * @param[in] max_packet_size Max packet size of the endpoint.
+ * @param[in] interval Polling interval.
+ * @return Error code.
+ */
+static int register_endpoint(ddf_fun_t *fun,
+    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	VHC_DATA(vhc, fun);
+
+	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	if (ep == NULL) {
+		return ENOMEM;
+	}
+
+	int rc = endpoint_init(ep, address, endpoint, direction, transfer_type,
+	    USB_SPEED_FULL, 1);
+	if (rc != EOK) {
+		free(ep);
+		return rc;
+	}
+
+	rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
+	if (rc != EOK) {
+		endpoint_destroy(ep);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Unregister endpoint (free some bandwidth reservation).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint Endpoint number.
+ * @param[in] direction Endpoint data direction.
+ * @return Error code.
+ */
+static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	VHC_DATA(vhc, fun);
+
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
+	    address, endpoint, direction, NULL);
+	if (ep == NULL) {
+		return ENOENT;
+	}
+
+	int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
+	    address, endpoint, direction);
+
+	return rc;
+}
+
+/** Schedule interrupt out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	VHC_DATA(vhc, fun);
+
+	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
+	    target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_INTERRUPT,
+	    fun, arg);
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->data_buffer = data;
+	transfer->data_buffer_size = size;
+	transfer->callback_out = callback;
+
+	int rc = vhc_virtdev_add_transfer(vhc, transfer);
+	if (rc != EOK) {
+		free(transfer);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Schedule interrupt in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	VHC_DATA(vhc, fun);
+
+	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
+	    target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_INTERRUPT,
+	    fun, arg);
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->data_buffer = data;
+	transfer->data_buffer_size = size;
+	transfer->callback_in = callback;
+
+	int rc = vhc_virtdev_add_transfer(vhc, transfer);
+	if (rc != EOK) {
+		free(transfer);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Schedule bulk out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_out(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	UNSUPPORTED("bulk_out");
+
+	return ENOTSUP;
+}
+
+/** Schedule bulk in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_in(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	UNSUPPORTED("bulk_in");
+
+	return ENOTSUP;
+}
+
+/** Schedule control write transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Data buffer (in USB endianess, allocated and
+ *	deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_write(ddf_fun_t *fun, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data_buffer, size_t data_buffer_size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	VHC_DATA(vhc, fun);
+
+	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
+	    target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_CONTROL,
+	    fun, arg);
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->setup_buffer = setup_packet;
+	transfer->setup_buffer_size = setup_packet_size;
+	transfer->data_buffer = data_buffer;
+	transfer->data_buffer_size = data_buffer_size;
+	transfer->callback_out = callback;
+
+	int rc = vhc_virtdev_add_transfer(vhc, transfer);
+	if (rc != EOK) {
+		free(transfer);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Schedule control read transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_read(ddf_fun_t *fun, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data_buffer, size_t data_buffer_size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	VHC_DATA(vhc, fun);
+
+	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
+	    target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_CONTROL,
+	    fun, arg);
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->setup_buffer = setup_packet;
+	transfer->setup_buffer_size = setup_packet_size;
+	transfer->data_buffer = data_buffer;
+	transfer->data_buffer_size = data_buffer_size;
+	transfer->callback_in = callback;
+
+	int rc = vhc_virtdev_add_transfer(vhc, transfer);
+	if (rc != EOK) {
+		free(transfer);
+		return rc;
+	}
+
+	return EOK;
+}
+
+static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	UNSUPPORTED("tell_address");
+
+	return ENOTSUP;
+}
+
+static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
+    devman_handle_t *handle)
+{
+	VHC_DATA(vhc, root_hub_fun);
+
+	*handle = vhc->hc_fun->handle;
+
+	return EOK;
+}
+
+static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	VHC_DATA(vhc, root_hub_fun);
+
+	if (handle == 0) {
+		handle = root_hub_fun->handle;
+	}
+
+	usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
+	usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle);
+	if (addr < 0) {
+		return addr;
+	} else {
+		*address = addr;
+		return EOK;
+	}
+}
+
+usbhc_iface_t vhc_iface = {
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.find_by_address = find_by_address,
+	.release_address = release_address,
+
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.bulk_in = bulk_in,
+	.bulk_out = bulk_out,
+
+	.control_write = control_write,
+	.control_read = control_read
+};
+
+usb_iface_t vhc_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_hc_impl,
+	.get_address = tell_address
+};
+
+usb_iface_t rh_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_rh_impl,
+	.get_address = tell_address_rh
+};
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/devconn.c
===================================================================
--- uspace/drv/bus/usb/vhc/devconn.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/devconn.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include "vhcd.h"
+#include "hub/virthub.h"
+
+
+static vhc_virtdev_t *vhc_virtdev_create()
+{
+	vhc_virtdev_t *dev = malloc(sizeof(vhc_virtdev_t));
+	if (dev == NULL) {
+		return NULL;
+	}
+	dev->address = 0;
+	dev->dev_sess = NULL;
+	dev->dev_local = NULL;
+	dev->plugged = true;
+	link_initialize(&dev->link);
+	fibril_mutex_initialize(&dev->guard);
+	list_initialize(&dev->transfer_queue);
+
+	return dev;
+}
+
+static int vhc_virtdev_plug_generic(vhc_data_t *vhc,
+    async_sess_t *sess, usbvirt_device_t *virtdev,
+    uintptr_t *handle, bool connect)
+{
+	vhc_virtdev_t *dev = vhc_virtdev_create();
+	if (dev == NULL) {
+		return ENOMEM;
+	}
+
+	dev->dev_sess = sess;
+	dev->dev_local = virtdev;
+
+	fibril_mutex_lock(&vhc->guard);
+	list_append(&dev->link, &vhc->devices);
+	fibril_mutex_unlock(&vhc->guard);
+
+	fid_t fibril = fibril_create(vhc_transfer_queue_processor, dev);
+	if (fibril == 0) {
+		free(dev);
+		return ENOMEM;
+	}
+	fibril_add_ready(fibril);
+
+	if (handle != NULL) {
+		*handle = (uintptr_t) dev;
+	}
+
+	if (connect) {
+		// FIXME: check status
+		(void) virthub_connect_device(vhc->hub, dev);
+	}
+
+	return EOK;
+}
+
+int vhc_virtdev_plug(vhc_data_t *vhc, async_sess_t *sess, uintptr_t *handle)
+{
+	return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true);
+}
+
+int vhc_virtdev_plug_local(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
+{
+	return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true);
+}
+
+int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
+{
+	return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false);
+}
+
+void vhc_virtdev_unplug(vhc_data_t *vhc, uintptr_t handle)
+{
+	vhc_virtdev_t *dev = (vhc_virtdev_t *) handle;
+
+	// FIXME: check status
+	(void) virthub_disconnect_device(vhc->hub, dev);
+
+	fibril_mutex_lock(&vhc->guard);
+	fibril_mutex_lock(&dev->guard);
+	dev->plugged = false;
+	list_remove(&dev->link);
+	fibril_mutex_unlock(&dev->guard);
+	fibril_mutex_unlock(&vhc->guard);
+}
Index: uspace/drv/bus/usb/vhc/hub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,135 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Virtual USB hub.
+ */
+
+#include <usb/classes/classes.h>
+#include <usbvirt/device.h>
+#include <errno.h>
+#include <async.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <ddf/driver.h>
+#include <devman.h>
+#include <usb/dev/hub.h>
+#include <usb/dev/recognise.h>
+
+#include "hub.h"
+#include "vhcd.h"
+#include "conn.h"
+
+usbvirt_device_t virtual_hub_device = {
+	.name = "root hub",
+	.ops = &hub_ops,
+	.address = 0
+};
+
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &rh_usb_iface,
+};
+
+static int hub_register_in_devman_fibril(void *arg);
+
+void virtual_hub_device_init(ddf_fun_t *hc_dev)
+{
+	virthub_init(&virtual_hub_device);
+
+	/*
+	 * We need to register the root hub.
+	 * This must be done in separate fibril because the device
+	 * we are connecting to are ourselves and we cannot connect
+	 * before leaving the add_device() function.
+	 */
+	fid_t root_hub_registration
+	    = fibril_create(hub_register_in_devman_fibril, hc_dev);
+	if (root_hub_registration == 0) {
+		usb_log_fatal("Failed to create hub registration fibril.\n");
+		return;
+	}
+
+	fibril_add_ready(root_hub_registration);
+}
+
+static int pretend_port_rest(int unused, void *unused2)
+{
+	return EOK;
+}
+
+/** Register root hub in devman.
+ *
+ * @param arg Host controller device (type <code>device_t *</code>).
+ * @return Error code.
+ */
+int hub_register_in_devman_fibril(void *arg)
+{
+	ddf_fun_t *hc_dev = (ddf_fun_t *) arg;
+
+	/*
+	 * Wait until parent device is properly initialized.
+	 */
+	async_sess_t *sess;
+	do {
+		sess = devman_device_connect(EXCHANGE_SERIALIZE, hc_dev->handle, 0);
+	} while (!sess);
+	async_hangup(sess);
+
+	int rc;
+
+	usb_hc_connection_t hc_conn;
+	rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
+	assert(rc == EOK);
+
+	rc = usb_hc_connection_open(&hc_conn);
+	assert(rc == EOK);
+
+	ddf_fun_t *hub_dev;
+	rc = usb_hc_new_device_wrapper(hc_dev->dev, &hc_conn,
+	    USB_SPEED_FULL,
+	    pretend_port_rest, 0, NULL,
+	    NULL, NULL, &rh_ops, hc_dev, &hub_dev);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to create root hub: %s.\n",
+		    str_error(rc));
+	}
+
+	usb_hc_connection_close(&hc_conn);
+
+	usb_log_info("Created root hub function (handle %zu).\n",
+	    (size_t) hub_dev->handle);
+
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub.h
===================================================================
--- uspace/drv/bus/usb/vhc/hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,52 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Virtual USB hub.
+ */
+
+#ifndef VHCD_HUB_H_
+#define VHCD_HUB_H_
+
+#include <usbvirt/device.h>
+#include <ddf/driver.h>
+
+#include "hub/hub.h"
+#include "hub/virthub.h"
+
+extern usbvirt_device_t virtual_hub_device;
+
+void virtual_hub_device_init(ddf_fun_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/hub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub/hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/hub/hub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,523 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Representation of an USB hub (implementation).
+ */
+#include <usb/classes/classes.h>
+#include <usbvirt/device.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ddf/driver.h>
+#include <usb/debug.h>
+
+#include "hub.h"
+
+
+/** Produce a byte from bit values.
+ */
+#define MAKE_BYTE(b0, b1, b2, b3, b4, b5, b6, b7) \
+	(( \
+		((b0) << 0) \
+		| ((b1) << 1) \
+		| ((b2) << 2) \
+		| ((b3) << 3) \
+		| ((b4) << 4) \
+		| ((b5) << 5) \
+		| ((b6) << 6) \
+		| ((b7) << 7) \
+	))
+
+/* Static functions. */
+static hub_port_t *get_hub_port(hub_t *, size_t);
+static void set_port_status_change(hub_port_t *, hub_status_change_t);
+static void clear_port_status_change(hub_port_t *, uint16_t);
+static int set_port_state_delayed_fibril(void *);
+static void set_port_state_delayed(hub_t *, size_t, suseconds_t,
+    hub_port_state_t, hub_port_state_t);
+
+/** Convert hub port state to a char. */
+char hub_port_state_to_char(hub_port_state_t state) {
+	switch (state) {
+		case HUB_PORT_STATE_NOT_CONFIGURED:
+			return '-';
+		case HUB_PORT_STATE_POWERED_OFF:
+			return 'O';
+		case HUB_PORT_STATE_DISCONNECTED:
+			return 'X';
+		case HUB_PORT_STATE_DISABLED:
+			return 'D';
+		case HUB_PORT_STATE_RESETTING:
+			return 'R';
+		case HUB_PORT_STATE_ENABLED:
+			return 'E';
+		case HUB_PORT_STATE_SUSPENDED:
+			return 'S';
+		case HUB_PORT_STATE_RESUMING:
+			return 'F';
+		default:
+			return '?';
+	}
+}
+
+/** Initialize single hub port.
+ *
+ * @param port Port to be initialized.
+ * @param index Port index (one based).
+ */
+static void hub_init_port(hub_port_t *port, hub_t *hub, size_t index)
+{
+	port->connected_device = NULL;
+	port->index = index;
+	port->state = HUB_PORT_STATE_NOT_CONFIGURED;
+	port->status_change = 0;
+	port->hub = hub;
+}
+
+/** Initialize the hub.
+ *
+ * @param hub Hub to be initialized.
+ */
+void hub_init(hub_t *hub)
+{
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_init_port(&hub->ports[i], hub, i + 1);
+	}
+	hub->custom_data = NULL;
+	hub->signal_changes = true;
+	fibril_mutex_initialize(&hub->guard);
+}
+
+/** Connect a device to the hub.
+ *
+ * @param hub Hub to connect device to.
+ * @param device Device to be connected.
+ * @return Index of port the device was connected to.
+ * @retval -1 No free port available.
+ */
+size_t hub_connect_device(hub_t *hub, void *device)
+{
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_port_t *port = &hub->ports[i];
+
+		if (port->connected_device != NULL) {
+			continue;
+		}
+
+		port->connected_device = device;
+
+		/*
+		 * TODO:
+		 * If the hub was configured, we can normally
+		 * announce the plug-in.
+		 * Otherwise, we will wait until hub is configured
+		 * and announce changes in single burst.
+		 */
+		//if (port->state == HUB_PORT_STATE_DISCONNECTED) {
+			port->state = HUB_PORT_STATE_DISABLED;
+			set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
+		//}
+
+		return i;
+	}
+
+	return (size_t) -1;
+}
+
+/** Disconnects a device from a hub.
+ *
+ * @param hub Hub the device was connected to.
+ * @param device Device to be disconnected.
+ * @return Error code.
+ */
+int hub_disconnect_device(hub_t *hub, void *device)
+{
+	size_t index = hub_find_device(hub, device);
+	if (index == (size_t) -1) {
+		return ENOENT;
+	}
+
+	hub_port_t *port = &hub->ports[index];
+
+	port->connected_device = NULL;
+	port->state = HUB_PORT_STATE_DISCONNECTED;
+	set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
+
+	return EOK;
+}
+
+/** Find port device is connected to.
+ *
+ * @param hub Hub in question.
+ * @param device Device in question.
+ * @return Port index (zero based).
+ * @retval -1 Device is not connected.
+ */
+size_t hub_find_device(hub_t *hub, void *device)
+{
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_port_t *port = &hub->ports[i];
+
+		if (port->connected_device == device) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+
+/** Acquire exclusive access to the hub.
+ *
+ * @param hub Hub in question.
+ */
+void hub_acquire(hub_t *hub)
+{
+	fibril_mutex_lock(&hub->guard);
+}
+
+/** Give up exclusive access to the hub.
+ *
+ * @param hub Hub in question.
+ */
+void hub_release(hub_t *hub)
+{
+	fibril_mutex_unlock(&hub->guard);
+}
+
+/** Change port state.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @param state New port state.
+ */
+void hub_set_port_state(hub_t *hub, size_t port_index, hub_port_state_t state)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return;
+	}
+
+	usb_log_debug("Setting port %zu to state %d.\n", port_index, state);
+
+	switch (state) {
+		case HUB_PORT_STATE_POWERED_OFF:
+			clear_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
+			clear_port_status_change(port, HUB_STATUS_C_PORT_ENABLE);
+			clear_port_status_change(port, HUB_STATUS_C_PORT_RESET);
+			break;
+		case HUB_PORT_STATE_RESUMING:
+			port->state = state;
+			set_port_state_delayed(hub, port_index,
+			    10, state, HUB_PORT_STATE_ENABLED);
+			break;
+		case HUB_PORT_STATE_RESETTING:
+			port->state = state;
+			set_port_state_delayed(hub, port_index,
+			    10, state, HUB_PORT_STATE_ENABLED);
+			break;
+		case HUB_PORT_STATE_ENABLED:
+			if (port->state == HUB_PORT_STATE_RESETTING) {
+				set_port_status_change(port, HUB_STATUS_C_PORT_RESET);
+			}
+			break;
+		default:
+			break;
+	}
+
+	port->state = state;
+}
+
+/** Change state of all ports.
+ *
+ * @param hub Hub in question.
+ * @param state New state for all ports.
+ */
+void hub_set_port_state_all(hub_t *hub, hub_port_state_t state)
+{
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_set_port_state(hub, i, state);
+	}
+}
+
+/** Get port state.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @return Port state.
+ */
+hub_port_state_t hub_get_port_state(hub_t *hub, size_t port_index)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return HUB_PORT_STATE_UNKNOWN;
+	}
+
+	return port->state;
+}
+
+/** Clear port status change bit.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @param change Change to be cleared.
+ */
+void hub_clear_port_status_change(hub_t *hub, size_t port_index,
+    hub_status_change_t change)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return;
+	}
+
+	clear_port_status_change(port, change);
+}
+
+/** Get port status change bits.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @return Port status change bitmap in standard format.
+ */
+uint16_t hub_get_port_status_change(hub_t *hub, size_t port_index)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return 0;
+	}
+
+	return port->status_change;
+}
+
+/** Get port status bits.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @return Port status bitmap in standard format.
+ */
+uint32_t hub_get_port_status(hub_t *hub, size_t port_index)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return 0;
+	}
+
+	uint32_t status;
+	status = MAKE_BYTE(
+	    /* Current connect status. */
+	    port->connected_device == NULL ? 0 : 1,
+	    /* Port enabled/disabled. */
+	    port->state == HUB_PORT_STATE_ENABLED ? 1 : 0,
+	    /* Suspend. */
+	    (port->state == HUB_PORT_STATE_SUSPENDED)
+		|| (port->state == HUB_PORT_STATE_RESUMING) ? 1 : 0,
+	    /* Over-current. */
+	    0,
+	    /* Reset. */
+	    port->state == HUB_PORT_STATE_RESETTING ? 1 : 0,
+	    /* Reserved. */
+	    0, 0, 0)
+
+	    | (MAKE_BYTE(
+	    /* Port power. */
+	    port->state == HUB_PORT_STATE_POWERED_OFF ? 0 : 1,
+	    /* Full-speed device. */
+	    0,
+	    /* Reserved. */
+	    0, 0, 0, 0, 0, 0
+	    )) << 8;
+
+	status |= (port->status_change << 16);
+
+	return status;
+}
+
+/** Create hub status change bitmap.
+ *
+ * @warning This function assumes that the whole bitmap fits into 8 bits.
+ *
+ * @param hub Hub in question.
+ * @return Hub status change bitmap.
+ */
+uint8_t hub_get_status_change_bitmap(hub_t *hub)
+{
+	uint8_t change_map = 0;
+
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_port_t *port = &hub->ports[i];
+
+		if (port->status_change != 0) {
+			change_map |= (1 << port->index);
+		}
+	}
+
+	return change_map;
+}
+
+
+/*
+ *
+ * STATIC (HELPER) FUNCTIONS
+ *
+ */
+
+/** Find a port in a hub.
+ *
+ * @param hub Hub in question.
+ * @param port Port index (zero based).
+ * @return Port structure.
+ * @retval NULL Invalid port index.
+ */
+static hub_port_t *get_hub_port(hub_t *hub, size_t port)
+{
+	if (port >= HUB_PORT_COUNT) {
+		return NULL;
+	}
+
+	return &hub->ports[port];
+}
+
+/** Adds a port status change to a port.
+ *
+ * @param port The port with status change.
+ * @param change Change to be added to the status.
+ */
+static void set_port_status_change(hub_port_t *port,
+    hub_status_change_t change)
+{
+	assert(port != NULL);
+	uint16_t old_value = port->status_change;
+	port->status_change |= change;
+	usb_log_debug("Changing status change on %zu: %04x => %04x\n",
+	    port->index,
+	    (unsigned int) old_value, (unsigned int) port->status_change);
+	port->hub->signal_changes = true;
+}
+
+/** Clears a port status change on a port.
+ *
+ * @param port The port with status change.
+ * @param change Change to be removed from the status.
+ */
+static void clear_port_status_change(hub_port_t *port,
+    uint16_t change)
+{
+	assert(port != NULL);
+	port->status_change &= (~change);
+	port->hub->signal_changes = true;
+}
+
+/** Structure for automatic (delayed) port state change. */
+struct delay_port_state_change {
+	/** Delay in microseconds. */
+	suseconds_t delay;
+	/** Old state of the port. */
+	hub_port_state_t old_state;
+	/** New state of the port. */
+	hub_port_state_t new_state;
+	/** Port index (zero based). */
+	size_t port;
+	/** Hub. */
+	hub_t *hub;
+};
+
+/** Fibril responsible for delayed port state change.
+ *
+ * @param arg Pointer to delay_port_state_change.
+ * @return Always EOK.
+ */
+static int set_port_state_delayed_fibril(void *arg)
+{
+	struct delay_port_state_change *change
+	    = (struct delay_port_state_change *) arg;
+
+	async_usleep(change->delay);
+
+	hub_acquire(change->hub);
+
+	hub_port_t *port = get_hub_port(change->hub, change->port);
+	assert(port != NULL);
+
+	if (port->state == change->old_state) {
+		hub_set_port_state(change->hub, change->port,
+		    change->new_state);
+	}
+
+	hub_release(change->hub);
+
+	free(change);
+
+	return EOK;
+}
+
+/** Change port state with a delay.
+ *
+ * @warning If the port state changes during the waiting phase, the state
+ * is not changed.
+ *
+ * @param hub Hub in question.
+ * @param port_index Port index (zero based).
+ * @param delay_time_ms Delay time in miliseconds.
+ * @param old_state Old (current) state of the port.
+ * @param new_state New state of the port.
+ */
+static void set_port_state_delayed(hub_t *hub, size_t port_index,
+    suseconds_t delay_time_ms,
+    hub_port_state_t old_state, hub_port_state_t new_state)
+{
+	struct delay_port_state_change *change
+	    = malloc(sizeof(struct delay_port_state_change));
+
+	change->hub = hub;
+	change->port = port_index;
+	change->delay = delay_time_ms * 1000;
+	change->old_state = old_state;
+	change->new_state = new_state;
+	fid_t fibril = fibril_create(set_port_state_delayed_fibril, change);
+	if (fibril == 0) {
+		printf("Failed to create fibril\n");
+		free(change);
+		return;
+	}
+	fibril_add_ready(fibril);
+}
+
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/hub.h
===================================================================
--- uspace/drv/bus/usb/vhc/hub/hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/hub/hub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,120 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Representation of an USB hub.
+ */
+#ifndef VHC_HUB_HUB_H_
+#define VHC_HUB_HUB_H_
+
+#include <fibril_synch.h>
+
+#ifndef HUB_PORT_COUNT
+#define HUB_PORT_COUNT 2
+#endif
+#define BITS2BYTES(bits) (bits ? ((((bits)-1)>>3)+1) : 0)
+
+/** Hub port internal state.
+ * Some states (e.g. port over current) are not covered as they are not
+ * simulated at all.
+ */
+typedef enum {
+	HUB_PORT_STATE_UNKNOWN,
+	HUB_PORT_STATE_NOT_CONFIGURED,
+	HUB_PORT_STATE_POWERED_OFF,
+	HUB_PORT_STATE_DISCONNECTED,
+	HUB_PORT_STATE_DISABLED,
+	HUB_PORT_STATE_RESETTING,
+	HUB_PORT_STATE_ENABLED,
+	HUB_PORT_STATE_SUSPENDED,
+	HUB_PORT_STATE_RESUMING,
+	/* HUB_PORT_STATE_, */
+} hub_port_state_t;
+
+char hub_port_state_to_char(hub_port_state_t);
+
+/** Hub status change mask bits. */
+typedef enum {
+	HUB_STATUS_C_PORT_CONNECTION = (1 << 0),
+	HUB_STATUS_C_PORT_ENABLE = (1 << 1),
+	HUB_STATUS_C_PORT_SUSPEND = (1 << 2),
+	HUB_STATUS_C_PORT_OVER_CURRENT = (1 << 3),
+	HUB_STATUS_C_PORT_RESET = (1 << 4),
+	/* HUB_STATUS_C_ = (1 << ), */
+} hub_status_change_t;
+
+typedef struct hub hub_t;
+
+/** Hub port information. */
+typedef struct {
+	/** Custom pointer to connected device. */
+	void *connected_device;
+	/** Port index (one based). */
+	size_t index;
+	/** Port state. */
+	hub_port_state_t state;
+	/** Status change bitmap. */
+	uint16_t status_change;
+	/** Containing hub. */
+	hub_t *hub;
+} hub_port_t;
+
+/** Hub device type. */
+struct hub {
+	/** Hub ports. */
+	hub_port_t ports[HUB_PORT_COUNT];
+	/** Custom hub data. */
+	void *custom_data;
+	/** Access guard to the whole hub. */
+	fibril_mutex_t guard;
+	/** Last value of status change bitmap. */
+	bool signal_changes;
+};
+
+void hub_init(hub_t *);
+size_t hub_connect_device(hub_t *, void *);
+int hub_disconnect_device(hub_t *, void *);
+size_t hub_find_device(hub_t *, void *);
+void hub_acquire(hub_t *);
+void hub_release(hub_t *);
+void hub_set_port_state(hub_t *, size_t, hub_port_state_t);
+void hub_set_port_state_all(hub_t *, hub_port_state_t);
+hub_port_state_t hub_get_port_state(hub_t *, size_t);
+void hub_clear_port_status_change(hub_t *, size_t, hub_status_change_t);
+uint16_t hub_get_port_status_change(hub_t *, size_t);
+uint32_t hub_get_port_status(hub_t *, size_t);
+uint8_t hub_get_status_change_bitmap(hub_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/virthub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub/virthub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/hub/virthub.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,260 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief
+ */
+#include <usb/classes/classes.h>
+#include <usbvirt/device.h>
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ddf/driver.h>
+
+#include "virthub.h"
+#include "hub.h"
+
+
+/** Standard device descriptor. */
+usb_standard_device_descriptor_t std_device_descriptor = {
+	.length = sizeof(usb_standard_device_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_DEVICE,
+	.usb_spec_version = 0x110,
+	.device_class = USB_CLASS_HUB,
+	.device_subclass = 0,
+	.device_protocol = 0,
+	.max_packet_size = 64,
+	.configuration_count = 1
+};
+
+/** Standard interface descriptor. */
+usb_standard_interface_descriptor_t std_interface_descriptor = {
+	.length = sizeof(usb_standard_interface_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_INTERFACE,
+	.interface_number = 0,
+	.alternate_setting = 0,
+	.endpoint_count = 1,
+	.interface_class = USB_CLASS_HUB,
+	.interface_subclass = 0,
+	.interface_protocol = 0,
+	.str_interface = 0
+};
+
+/** Hub descriptor. */
+hub_descriptor_t hub_descriptor = {
+	.length = sizeof(hub_descriptor_t),
+	.type = USB_DESCTYPE_HUB,
+	.port_count = HUB_PORT_COUNT,
+	.characteristics = 0, 
+	.power_on_warm_up = 50, /* Huh? */
+	.max_current = 100, /* Huh again. */
+	.removable_device = { 0 },
+	.port_power = { 0xFF }
+};
+
+/** Endpoint descriptor. */
+usb_standard_endpoint_descriptor_t endpoint_descriptor = {
+	.length = sizeof(usb_standard_endpoint_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_ENDPOINT,
+	.endpoint_address = HUB_STATUS_CHANGE_PIPE | 128,
+	.attributes = USB_TRANSFER_INTERRUPT,
+	.max_packet_size = 8,
+	.poll_interval = 0xFF
+};
+
+/** Standard configuration descriptor. */
+usb_standard_configuration_descriptor_t std_configuration_descriptor = {
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
+	.total_length = 
+		sizeof(usb_standard_configuration_descriptor_t)
+		+ sizeof(std_interface_descriptor)
+		+ sizeof(hub_descriptor)
+		+ sizeof(endpoint_descriptor)
+		,
+	.interface_count = 1,
+	.configuration_number = HUB_CONFIGURATION_ID,
+	.str_configuration = 0,
+	.attributes = 128, /* denotes bus-powered device */
+	.max_power = 50
+};
+
+/** All hub configuration descriptors. */
+static usbvirt_device_configuration_extras_t extra_descriptors[] = {
+	{
+		.data = (uint8_t *) &std_interface_descriptor,
+		.length = sizeof(std_interface_descriptor)
+	},
+	{
+		.data = (uint8_t *) &hub_descriptor,
+		.length = sizeof(hub_descriptor)
+	},
+	{
+		.data = (uint8_t *) &endpoint_descriptor,
+		.length = sizeof(endpoint_descriptor)
+	}
+};
+
+/** Hub configuration. */
+usbvirt_device_configuration_t configuration = {
+	.descriptor = &std_configuration_descriptor,
+	.extra = extra_descriptors,
+	.extra_count = sizeof(extra_descriptors)/sizeof(extra_descriptors[0])
+};
+
+/** Hub standard descriptors. */
+usbvirt_descriptors_t descriptors = {
+	.device = &std_device_descriptor,
+	.configuration = &configuration,
+	.configuration_count = 1,
+};
+
+/** Initializes virtual hub device.
+ *
+ * @param dev Virtual USB device backend.
+ * @return Error code.
+ */
+int virthub_init(usbvirt_device_t *dev)
+{
+	if (dev == NULL) {
+		return EBADMEM;
+	}
+	dev->ops = &hub_ops;
+	dev->descriptors = &descriptors;
+
+	hub_t *hub = malloc(sizeof(hub_t));
+	if (hub == NULL) {
+		return ENOMEM;
+	}
+
+	hub_init(hub);
+	dev->device_data = hub;
+
+	return EOK;
+}
+
+/** Connect a device to a virtual hub.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param conn Device to be connected.
+ * @return Port device was connected to.
+ */
+int virthub_connect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
+{
+	assert(dev != NULL);
+	assert(conn != NULL);
+
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+	size_t port = hub_connect_device(hub, conn);
+	hub_release(hub);
+
+	return port;
+}
+
+/** Disconnect a device from a virtual hub.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param conn Device to be disconnected.
+ * @return Error code.
+ */
+int virthub_disconnect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
+{
+	assert(dev != NULL);
+	assert(conn != NULL);
+
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+	hub_disconnect_device(hub, conn);
+	hub_release(hub);
+
+	return EOK;
+}
+
+/** Whether trafic is propagated to given device.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param conn Connected device.
+ * @return Whether port is signalling to the device.
+ */
+bool virthub_is_device_enabled(usbvirt_device_t *dev, vhc_virtdev_t *conn)
+{
+	assert(dev != NULL);
+	assert(conn != NULL);
+
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+
+	hub_port_state_t state = HUB_PORT_STATE_UNKNOWN;
+	size_t port = hub_find_device(hub, conn);
+	if (port != (size_t) -1) {
+		state = hub_get_port_state(hub, port);
+	}
+	hub_release(hub);
+
+	return state == HUB_PORT_STATE_ENABLED;
+}
+
+/** Format status of a virtual hub.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param[out] status Hub status information.
+ * @param[in] len Size of the @p status buffer.
+ */
+void virthub_get_status(usbvirt_device_t *dev, char *status, size_t len)
+{
+	assert(dev != NULL);
+	if (len == 0) {
+		return;
+	}
+
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	char port_status[HUB_PORT_COUNT + 1];
+
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		port_status[i] = hub_port_state_to_char(
+		    hub_get_port_state(hub, i));
+	}
+	port_status[HUB_PORT_COUNT] = 0;
+
+	snprintf(status, len, "vhub:%s", port_status);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/virthub.h
===================================================================
--- uspace/drv/bus/usb/vhc/hub/virthub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/hub/virthub.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,90 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief USB hub as a virtual USB device.
+ */
+#ifndef VHC_HUB_VIRTHUB_H_
+#define VHC_HUB_VIRTHUB_H_
+
+#include <usbvirt/device.h>
+#include "hub.h"
+
+#ifdef STANDALONE_HUB
+#define virtdev_connection_t int
+#else
+#include "../vhcd.h"
+#endif
+
+/** Endpoint number for status change pipe. */
+#define HUB_STATUS_CHANGE_PIPE 1
+/** Configuration value for hub configuration. */
+#define HUB_CONFIGURATION_ID 1
+
+
+/** Hub descriptor.
+ */
+typedef struct {
+	/** Size of this descriptor in bytes. */
+	uint8_t length;
+	/** Descriptor type (USB_DESCTYPE_HUB). */
+	uint8_t type;
+	/** Number of downstream ports. */
+	uint8_t port_count;
+	/** Hub characteristics. */
+	uint16_t characteristics;
+	/** Time from power-on to stabilized current.
+	 * Expressed in 2ms unit.
+	 */
+	uint8_t power_on_warm_up;
+	/** Maximum current (in mA). */
+	uint8_t max_current;
+	/** Whether device at given port is removable. */
+	uint8_t removable_device[BITS2BYTES(HUB_PORT_COUNT+1)];
+	/** Port power control.
+	 * This is USB1.0 compatibility field, all bits must be 1.
+	 */
+	uint8_t port_power[BITS2BYTES(HUB_PORT_COUNT+1)];
+} __attribute__ ((packed)) hub_descriptor_t;
+
+extern usbvirt_device_ops_t hub_ops;
+extern hub_descriptor_t hub_descriptor;
+
+int virthub_init(usbvirt_device_t *);
+int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *);
+int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *);
+bool virthub_is_device_enabled(usbvirt_device_t *, vhc_virtdev_t *);
+void virthub_get_status(usbvirt_device_t *, char *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/virthubops.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub/virthubops.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/hub/virthubops.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,457 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Virtual USB hub operations.
+ */
+#include <errno.h>
+#include <usb/classes/hub.h>
+#include <usbvirt/device.h>
+#include "virthub.h"
+#include "hub.h"
+
+/** Callback when device changes states. */
+static void on_state_change(usbvirt_device_t *dev,
+    usbvirt_device_state_t old_state, usbvirt_device_state_t new_state)
+{
+	hub_t *hub = (hub_t *)dev->device_data;
+
+	hub_acquire(hub);
+
+	switch (new_state) {
+		case USBVIRT_STATE_CONFIGURED:
+			hub_set_port_state_all(hub, HUB_PORT_STATE_POWERED_OFF);
+			break;
+		case USBVIRT_STATE_ADDRESS:
+			hub_set_port_state_all(hub, HUB_PORT_STATE_NOT_CONFIGURED);
+			break;
+		default:
+			break;
+	}
+
+	hub_release(hub);
+}
+
+/** Callback for data request. */
+static int req_on_status_change_pipe(usbvirt_device_t *dev,
+    usb_endpoint_t endpoint, usb_transfer_type_t tr_type,
+    void *buffer, size_t buffer_size, size_t *actual_size)
+{
+	if (endpoint != HUB_STATUS_CHANGE_PIPE) {
+		return ESTALL;
+	}
+	if (tr_type != USB_TRANSFER_INTERRUPT) {
+		return ESTALL;
+	}
+	
+	hub_t *hub = dev->device_data;
+
+	hub_acquire(hub);
+
+	if (!hub->signal_changes) {
+		hub_release(hub);
+
+		return ENAK;
+	}
+
+
+	uint8_t change_map = hub_get_status_change_bitmap(hub);
+
+	uint8_t *b = (uint8_t *) buffer;
+	if (buffer_size > 0) {
+		*b = change_map;
+		*actual_size = 1;
+	} else {
+		*actual_size = 0;
+	}
+	
+	hub->signal_changes = false;
+
+	hub_release(hub);
+
+	return EOK;
+}
+
+/** Handle ClearHubFeature request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_clear_hub_feature(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	return ENOTSUP;
+}
+
+/** Handle ClearPortFeature request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_clear_port_feature(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	int rc;
+	size_t port = request->index - 1;
+	usb_hub_class_feature_t feature = request->value;
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+
+	hub_port_state_t port_state = hub_get_port_state(hub, port);
+
+	switch (feature) {
+		case USB_HUB_FEATURE_PORT_ENABLE:
+			if ((port_state != HUB_PORT_STATE_NOT_CONFIGURED)
+			    && (port_state != HUB_PORT_STATE_POWERED_OFF)) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_DISABLED);
+			}
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_PORT_SUSPEND:
+			if (port_state != HUB_PORT_STATE_SUSPENDED) {
+				rc = EOK;
+				break;
+			}
+			hub_set_port_state(hub, port, HUB_PORT_STATE_RESUMING);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_PORT_POWER:
+			if (port_state != HUB_PORT_STATE_NOT_CONFIGURED) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_POWERED_OFF);
+			}
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_CONNECTION:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_CONNECTION);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_ENABLE:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_ENABLE);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_SUSPEND:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_SUSPEND);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_OVER_CURRENT:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_OVER_CURRENT);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_RESET:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_RESET);
+			rc = EOK;
+			break;
+
+		default:
+			rc = ENOTSUP;
+			break;
+	}
+
+	hub_release(hub);
+
+	return rc;
+}
+
+/** Handle GetBusState request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_get_bus_state(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	return ENOTSUP;
+}
+
+/** Handle GetDescriptor request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_get_descriptor(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	if (request->value_high == USB_DESCTYPE_HUB) {
+		usbvirt_control_reply_helper(request, data, act_size,
+		    &hub_descriptor, hub_descriptor.length);
+
+		return EOK;
+	}
+	/* Let the framework handle all the rest. */
+	return EFORWARD;
+}
+
+/** Handle GetHubStatus request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_get_hub_status(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	uint32_t hub_status = 0;
+
+	usbvirt_control_reply_helper(request, data, act_size,
+	    &hub_status, sizeof(hub_status));
+
+	return EOK;
+}
+
+/** Handle GetPortStatus request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_get_port_status(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+
+	uint32_t status = hub_get_port_status(hub, request->index - 1);
+
+	hub_release(hub);
+
+	usbvirt_control_reply_helper(request, data, act_size,
+	    &status, sizeof(status));
+
+	return EOK;
+}
+
+/** Handle SetHubFeature request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_set_hub_feature(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	return ENOTSUP;
+}
+
+/** Handle SetPortFeature request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_set_port_feature(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	int rc;
+	size_t port = request->index - 1;
+	usb_hub_class_feature_t feature = request->value;
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+
+	hub_port_state_t port_state = hub_get_port_state(hub, port);
+
+	switch (feature) {
+		case USB_HUB_FEATURE_PORT_RESET:
+			if (port_state != HUB_PORT_STATE_POWERED_OFF) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_RESETTING);
+			}
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_PORT_SUSPEND:
+			if (port_state == HUB_PORT_STATE_ENABLED) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_SUSPENDED);
+			}
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_PORT_POWER:
+			if (port_state == HUB_PORT_STATE_POWERED_OFF) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_DISCONNECTED);
+			}
+			rc = EOK;
+			break;
+
+		default:
+			break;
+	}
+
+	hub_release(hub);
+
+	return rc;
+}
+
+
+/** IN class request. */
+#define CLASS_REQ_IN(recipient) \
+	USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_IN, \
+	USBVIRT_REQUEST_TYPE_CLASS, recipient)
+/** OUT class request. */
+#define CLASS_REQ_OUT(recipient) \
+	USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_OUT, \
+	USBVIRT_REQUEST_TYPE_CLASS, recipient)
+
+/** Recipient: other. */
+#define REC_OTHER USB_REQUEST_RECIPIENT_OTHER
+/** Recipient: device. */
+#define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE
+/** Direction: in. */
+#define DIR_IN USB_DIRECTION_IN
+/** Direction: out. */
+#define DIR_OUT USB_DIRECTION_OUT
+
+
+/** Create a class request.
+ *
+ * @param direction Request direction.
+ * @param recipient Request recipient.
+ * @param req Request code.
+ */
+#define CLASS_REQ(direction, recipient, req) \
+	.req_direction = direction, \
+	.req_recipient = recipient, \
+	.req_type = USB_REQUEST_TYPE_CLASS, \
+	.request = req
+
+/** Create a standard request.
+ *
+ * @param direction Request direction.
+ * @param recipient Request recipient.
+ * @param req Request code.
+ */
+#define STD_REQ(direction, recipient, req) \
+	.req_direction = direction, \
+	.req_recipient = recipient, \
+	.req_type = USB_REQUEST_TYPE_STANDARD, \
+	.request = req
+
+/** Hub operations on control endpoint zero. */
+static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
+	{
+		STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
+		.name = "GetDescriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
+		.name = "GetDescriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
+		.name = "GetPortStatus",
+		.callback = req_get_port_status
+	},
+	{
+		CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
+		.name = "ClearHubFeature",
+		.callback = req_clear_hub_feature
+	},
+	{
+		CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
+		.name = "ClearPortFeature",
+		.callback = req_clear_port_feature
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATE),
+		.name = "GetBusState",
+		.callback = req_get_bus_state
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
+		.name = "GetHubDescriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),
+		.name = "GetHubStatus",
+		.callback = req_get_hub_status
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
+		.name = "GetPortStatus",
+		.callback = req_get_port_status
+	},
+	{
+		CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
+		.name = "SetHubFeature",
+		.callback = req_set_hub_feature
+	},
+	{
+		CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),
+		.name = "SetPortFeature",
+		.callback = req_set_port_feature
+	},
+	{
+		.callback = NULL
+	}
+};
+
+
+/** Hub operations. */
+usbvirt_device_ops_t hub_ops = {
+	.control = endpoint_zero_handlers,
+	.data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe,
+	.state_changed = on_state_change,
+};
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/main.c
===================================================================
--- uspace/drv/bus/usb/vhc/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/main.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,153 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * Virtual host controller.
+ */
+
+#include <devmap.h>
+#include <async.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb_iface.h>
+#include "vhcd.h"
+#include "hub.h"
+#include "conn.h"
+
+static ddf_dev_ops_t vhc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &vhc_iface,
+	.interfaces[USB_DEV_IFACE] = &vhc_usb_iface,
+	.close = on_client_close,
+	.default_handler = default_connection_handler
+};
+
+static int vhc_add_device(ddf_dev_t *dev)
+{
+	static int vhc_count = 0;
+	int rc;
+
+	if (vhc_count > 0) {
+		return ELIMIT;
+	}
+
+	vhc_data_t *data = malloc(sizeof(vhc_data_t));
+	if (data == NULL) {
+		usb_log_fatal("Failed to allocate memory.\n");
+		return ENOMEM;
+	}
+	data->magic = 0xDEADBEEF;
+	rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to initialize endpoint manager.\n");
+		free(data);
+		return rc;
+	}
+	usb_device_keeper_init(&data->dev_keeper);
+
+	ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
+	if (hc == NULL) {
+		usb_log_fatal("Failed to create device function.\n");
+		free(data);
+		return ENOMEM;
+	}
+
+	hc->ops = &vhc_ops;
+	list_initialize(&data->devices);
+	fibril_mutex_initialize(&data->guard);
+	data->hub = &virtual_hub_device;
+	data->hc_fun = hc;
+
+	dev->driver_data = data;
+
+	rc = ddf_fun_bind(hc);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to bind HC function: %s.\n",
+		    str_error(rc));
+		free(data);
+		return rc;
+	}
+
+	rc = ddf_fun_add_to_class(hc, USB_HC_DDF_CLASS_NAME);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to add function to HC class: %s.\n",
+		    str_error(rc));
+		free(data);
+		return rc;
+	}
+
+	virtual_hub_device_init(hc);
+
+	usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
+	    (size_t) dev->handle, (size_t) hc->handle);
+
+
+
+	rc = vhc_virtdev_plug_hub(data, data->hub, NULL);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc));
+		free(data);
+		return rc;
+	}
+
+	return EOK;
+}
+
+static driver_ops_t vhc_driver_ops = {
+	.add_device = vhc_add_device,
+};
+
+static driver_t vhc_driver = {
+	.name = NAME,
+	.driver_ops = &vhc_driver_ops
+};
+
+
+int main(int argc, char * argv[])
+{	
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	printf(NAME ": virtual USB host controller driver.\n");
+
+	return ddf_driver_main(&vhc_driver);
+}
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/transfer.c
===================================================================
--- uspace/drv/bus/usb/vhc/transfer.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/transfer.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,287 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <usbvirt/device.h>
+#include <usbvirt/ipc.h>
+#include "vhcd.h"
+
+vhc_transfer_t *vhc_transfer_create(usb_address_t address, usb_endpoint_t ep,
+    usb_direction_t dir, usb_transfer_type_t tr_type,
+    ddf_fun_t *fun, void *callback_arg)
+{
+	vhc_transfer_t *result = malloc(sizeof(vhc_transfer_t));
+	if (result == NULL) {
+		return NULL;
+	}
+	link_initialize(&result->link);
+	result->address = address;
+	result->endpoint = ep;
+	result->direction = dir;
+	result->transfer_type = tr_type;
+	result->setup_buffer = NULL;
+	result->setup_buffer_size = 0;
+	result->data_buffer = NULL;
+	result->data_buffer_size = 0;
+	result->ddf_fun = fun;
+	result->callback_arg = callback_arg;
+	result->callback_in = NULL;
+	result->callback_out = NULL;
+
+	usb_log_debug2("Created transfer %p (%d.%d %s %s)\n", result,
+	    address, ep, usb_str_transfer_type_short(tr_type),
+	    dir == USB_DIRECTION_IN ? "in" : "out");
+
+	return result;
+}
+
+static bool is_set_address_transfer(vhc_transfer_t *transfer)
+{
+	if (transfer->endpoint != 0) {
+		return false;
+	}
+	if (transfer->transfer_type != USB_TRANSFER_CONTROL) {
+		return false;
+	}
+	if (transfer->direction != USB_DIRECTION_OUT) {
+		return false;
+	}
+	if (transfer->setup_buffer_size != sizeof(usb_device_request_setup_packet_t)) {
+		return false;
+	}
+	usb_device_request_setup_packet_t *setup = transfer->setup_buffer;
+	if (setup->request_type != 0) {
+		return false;
+	}
+	if (setup->request != USB_DEVREQ_SET_ADDRESS) {
+		return false;
+	}
+
+	return true;
+}
+
+int vhc_virtdev_add_transfer(vhc_data_t *vhc, vhc_transfer_t *transfer)
+{
+	fibril_mutex_lock(&vhc->guard);
+
+	bool target_found = false;
+	list_foreach(vhc->devices, pos) {
+		vhc_virtdev_t *dev = list_get_instance(pos, vhc_virtdev_t, link);
+		fibril_mutex_lock(&dev->guard);
+		if (dev->address == transfer->address) {
+			if (target_found) {
+				usb_log_warning("Transfer would be accepted by more devices!\n");
+				goto next;
+			}
+			target_found = true;
+			list_append(&transfer->link, &dev->transfer_queue);
+		}
+next:
+		fibril_mutex_unlock(&dev->guard);
+	}
+
+	fibril_mutex_unlock(&vhc->guard);
+
+	if (target_found) {
+		return EOK;
+	} else {
+		return ENOENT;
+	}
+}
+
+static int process_transfer_local(vhc_transfer_t *transfer,
+    usbvirt_device_t *dev, size_t *actual_data_size)
+{
+	int rc;
+
+	if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
+		if (transfer->direction == USB_DIRECTION_IN) {
+			rc = usbvirt_control_read(dev,
+			    transfer->setup_buffer, transfer->setup_buffer_size,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    actual_data_size);
+		} else {
+			assert(transfer->direction == USB_DIRECTION_OUT);
+			rc = usbvirt_control_write(dev,
+			    transfer->setup_buffer, transfer->setup_buffer_size,
+			    transfer->data_buffer, transfer->data_buffer_size);
+		}
+	} else {
+		if (transfer->direction == USB_DIRECTION_IN) {
+			rc = usbvirt_data_in(dev, transfer->transfer_type,
+			    transfer->endpoint,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    actual_data_size);
+		} else {
+			assert(transfer->direction == USB_DIRECTION_OUT);
+			rc = usbvirt_data_out(dev, transfer->transfer_type,
+			    transfer->endpoint,
+			    transfer->data_buffer, transfer->data_buffer_size);
+		}
+	}
+
+	return rc;
+}
+
+static int process_transfer_remote(vhc_transfer_t *transfer,
+    async_sess_t *sess, size_t *actual_data_size)
+{
+	int rc;
+
+	if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
+		if (transfer->direction == USB_DIRECTION_IN) {
+			rc = usbvirt_ipc_send_control_read(sess,
+			    transfer->setup_buffer, transfer->setup_buffer_size,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    actual_data_size);
+		} else {
+			assert(transfer->direction == USB_DIRECTION_OUT);
+			rc = usbvirt_ipc_send_control_write(sess,
+			    transfer->setup_buffer, transfer->setup_buffer_size,
+			    transfer->data_buffer, transfer->data_buffer_size);
+		}
+	} else {
+		if (transfer->direction == USB_DIRECTION_IN) {
+			rc = usbvirt_ipc_send_data_in(sess, transfer->endpoint,
+			    transfer->transfer_type,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    actual_data_size);
+		} else {
+			assert(transfer->direction == USB_DIRECTION_OUT);
+			rc = usbvirt_ipc_send_data_out(sess, transfer->endpoint,
+			    transfer->transfer_type,
+			    transfer->data_buffer, transfer->data_buffer_size);
+		}
+	}
+
+	return rc;
+}
+
+static vhc_transfer_t *dequeue_first_transfer(vhc_virtdev_t *dev)
+{
+	assert(fibril_mutex_is_locked(&dev->guard));
+	assert(!list_empty(&dev->transfer_queue));
+
+	vhc_transfer_t *transfer = list_get_instance(
+	    list_first(&dev->transfer_queue), vhc_transfer_t, link);
+	list_remove(&transfer->link);
+
+	return transfer;
+}
+
+
+static void execute_transfer_callback_and_free(vhc_transfer_t *transfer,
+    size_t data_transfer_size, int outcome)
+{
+	assert(outcome != ENAK);
+
+	usb_log_debug2("Transfer %p ended: %s.\n",
+	    transfer, str_error(outcome));
+
+	if (transfer->direction == USB_DIRECTION_IN) {
+		transfer->callback_in(transfer->ddf_fun, outcome,
+		    data_transfer_size, transfer->callback_arg);
+	} else {
+		assert(transfer->direction == USB_DIRECTION_OUT);
+		transfer->callback_out(transfer->ddf_fun, outcome,
+		    transfer->callback_arg);
+	}
+
+	free(transfer);
+}
+
+int vhc_transfer_queue_processor(void *arg)
+{
+	vhc_virtdev_t *dev = arg;
+	fibril_mutex_lock(&dev->guard);
+	while (dev->plugged) {
+		if (list_empty(&dev->transfer_queue)) {
+			fibril_mutex_unlock(&dev->guard);
+			async_usleep(10 * 1000);
+			fibril_mutex_lock(&dev->guard);
+			continue;
+		}
+
+		vhc_transfer_t *transfer = dequeue_first_transfer(dev);
+		fibril_mutex_unlock(&dev->guard);
+
+		int rc = EOK;
+		size_t data_transfer_size = 0;
+		if (dev->dev_sess) {
+			rc = process_transfer_remote(transfer, dev->dev_sess,
+			    &data_transfer_size);
+		} else if (dev->dev_local != NULL) {
+			rc = process_transfer_local(transfer, dev->dev_local,
+			    &data_transfer_size);
+		} else {
+			usb_log_warning("Device has no remote phone nor local node.\n");
+			rc = ESTALL;
+		}
+
+		usb_log_debug2("Transfer %p processed: %s.\n",
+		    transfer, str_error(rc));
+
+		fibril_mutex_lock(&dev->guard);
+		if (rc == EOK) {
+			if (is_set_address_transfer(transfer)) {
+				usb_device_request_setup_packet_t *setup
+				    = transfer->setup_buffer;
+				dev->address = setup->value;
+				usb_log_debug2("Address changed to %d\n",
+				    dev->address);
+			}
+		}
+		if (rc == ENAK) {
+			// FIXME: this will work only because we do
+			// not NAK control transfers but this is generally
+			// a VERY bad idea indeed
+			list_append(&transfer->link, &dev->transfer_queue);
+		}
+		fibril_mutex_unlock(&dev->guard);
+
+		if (rc != ENAK) {
+			execute_transfer_callback_and_free(transfer,
+			    data_transfer_size, rc);
+		}
+
+		async_usleep(1000 * 100);
+		fibril_mutex_lock(&dev->guard);
+	}
+
+	/* Immediately fail all remaining transfers. */
+	while (!list_empty(&dev->transfer_queue)) {
+		vhc_transfer_t *transfer = dequeue_first_transfer(dev);
+		execute_transfer_callback_and_free(transfer, 0, EBADCHECKSUM);
+	}
+
+	fibril_mutex_unlock(&dev->guard);
+
+	return EOK;
+}
+
Index: uspace/drv/bus/usb/vhc/vhc.ma
===================================================================
--- uspace/drv/bus/usb/vhc/vhc.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/vhc.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,2 @@
+10 usb&hc=vhc
+
Index: uspace/drv/bus/usb/vhc/vhcd.h
===================================================================
--- uspace/drv/bus/usb/vhc/vhcd.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/bus/usb/vhc/vhcd.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,97 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Virtual USB host controller common definitions.
+ */
+#ifndef VHCD_VHCD_H_
+#define VHCD_VHCD_H_
+
+#include <usb/debug.h>
+#include <usbvirt/device.h>
+#include <usb/host/usb_endpoint_manager.h>
+#include <usb/host/device_keeper.h>
+#include <usbhc_iface.h>
+#include <async.h>
+
+#define NAME "vhc"
+
+typedef struct {
+	link_t link;
+	async_sess_t *dev_sess;
+	usbvirt_device_t *dev_local;
+	bool plugged;
+	usb_address_t address;
+	fibril_mutex_t guard;
+	list_t transfer_queue;
+} vhc_virtdev_t;
+
+typedef struct {
+	uint32_t magic;
+	list_t devices;
+	fibril_mutex_t guard;
+	usb_endpoint_manager_t ep_manager;
+	usb_device_keeper_t dev_keeper;
+	usbvirt_device_t *hub;
+	ddf_fun_t *hc_fun;
+} vhc_data_t;
+
+typedef struct {
+	link_t link;
+	usb_address_t address;
+	usb_endpoint_t endpoint;
+	usb_direction_t direction;
+	usb_transfer_type_t transfer_type;
+	void *setup_buffer;
+	size_t setup_buffer_size;
+	void *data_buffer;
+	size_t data_buffer_size;
+	ddf_fun_t *ddf_fun;
+	void *callback_arg;
+	usbhc_iface_transfer_in_callback_t callback_in;
+	usbhc_iface_transfer_out_callback_t callback_out;
+} vhc_transfer_t;
+
+vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t,
+    usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *);
+int vhc_virtdev_plug(vhc_data_t *, async_sess_t *, uintptr_t *);
+int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
+int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
+void vhc_virtdev_unplug(vhc_data_t *, uintptr_t);
+int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *);
+
+int vhc_transfer_queue_processor(void *arg);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/char/ns8250/Makefile
===================================================================
--- uspace/drv/char/ns8250/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/char/ns8250/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = ns8250
+
+SOURCES = \
+	ns8250.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/char/ns8250/cyclic_buffer.h
===================================================================
--- uspace/drv/char/ns8250/cyclic_buffer.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/char/ns8250/cyclic_buffer.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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 ns8250
+ * @{
+ */
+/** @file
+ */
+
+#ifndef CYCLIC_BUFFER_H_
+#define CYCLIC_BUFFER_H_
+
+#define BUF_LEN 256
+
+typedef struct cyclic_buffer {
+	uint8_t buf[BUF_LEN];
+	int start;
+	int cnt;
+}  cyclic_buffer_t;
+
+/*
+ * @return		False if the buffer is full.
+ */
+static inline bool buf_push_back(cyclic_buffer_t *buf, uint8_t item)
+{
+	if (buf->cnt >= BUF_LEN)
+		return false;
+	int pos = (buf->start + buf->cnt) % BUF_LEN;
+	buf->buf[pos] = item;
+	buf->cnt++;
+	return true;
+}
+
+static inline bool buf_is_empty(cyclic_buffer_t *buf)
+{
+	return buf->cnt == 0;
+}
+
+static inline uint8_t buf_pop_front(cyclic_buffer_t *buf)
+{
+	assert(!buf_is_empty(buf));
+	
+	uint8_t res = buf->buf[buf->start];
+	buf->start = (buf->start + 1) % BUF_LEN;
+	buf->cnt--;
+	return res;
+}
+
+static inline void buf_clear(cyclic_buffer_t *buf)
+{
+	buf->cnt = 0;
+}
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/char/ns8250/ns8250.c
===================================================================
--- uspace/drv/char/ns8250/ns8250.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/char/ns8250/ns8250.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,963 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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.
+ */
+
+/**
+ * @defgroup ns8250 Serial port driver.
+ * @brief HelenOS serial port driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+#include <malloc.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
+#include <ddf/log.h>
+#include <ops/char_dev.h>
+
+#include <devman.h>
+#include <ipc/devman.h>
+#include <device/hw_res.h>
+#include <ipc/serial_ctl.h>
+
+#include "cyclic_buffer.h"
+
+#define NAME "ns8250"
+
+#define REG_COUNT 7
+#define MAX_BAUD_RATE 115200
+#define DLAB_MASK (1 << 7)
+
+/** Obtain soft-state structure from function node */
+#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
+
+/** Obtain soft-state structure from device node */
+#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
+
+/** The number of bits of one data unit send by the serial port. */
+typedef enum {
+	WORD_LENGTH_5,
+	WORD_LENGTH_6,
+	WORD_LENGTH_7,
+	WORD_LENGTH_8
+} word_length_t;
+
+/** The number of stop bits used by the serial port. */
+typedef enum {
+	/** Use one stop bit. */
+	ONE_STOP_BIT,
+	/** 1.5 stop bits for word length 5, 2 stop bits otherwise. */
+	TWO_STOP_BITS
+} stop_bit_t;
+
+/** The driver data for the serial port devices. */
+typedef struct ns8250 {
+	/** DDF device node */
+	ddf_dev_t *dev;
+	/** DDF function node */
+	ddf_fun_t *fun;
+	/** Is there any client conntected to the device? */
+	bool client_connected;
+	/** The irq assigned to this device. */
+	int irq;
+	/** The base i/o address of the devices registers. */
+	uint32_t io_addr;
+	/** The i/o port used to access the serial ports registers. */
+	ioport8_t *port;
+	/** The buffer for incomming data. */
+	cyclic_buffer_t input_buffer;
+	/** The fibril mutex for synchronizing the access to the device. */
+	fibril_mutex_t mutex;
+} ns8250_t;
+
+/** Create per-device soft-state structure.
+ *
+ * @return	Pointer to soft-state structure.
+ */
+static ns8250_t *ns8250_new(void)
+{
+	ns8250_t *ns;
+	
+	ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));
+	if (ns == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&ns->mutex);
+	return ns;
+}
+
+/** Delete soft-state structure.
+ *
+ * @param ns	The driver data structure.
+ */
+static void ns8250_delete(ns8250_t *ns)
+{
+	assert(ns != NULL);
+	free(ns);
+}
+
+/** Find out if there is some incomming data available on the serial port.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @return		True if there are data waiting to be read, false
+ *			otherwise.
+ */
+static bool ns8250_received(ioport8_t *port)
+{
+	return (pio_read_8(port + 5) & 1) != 0;
+}
+
+/** Read one byte from the serial port.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @return		The data read.
+ */
+static uint8_t ns8250_read_8(ioport8_t *port)
+{
+	return pio_read_8(port);
+}
+
+/** Find out wheter it is possible to send data.
+ *
+ * @param port		The base address of the serial port device's ports.
+ */
+static bool is_transmit_empty(ioport8_t *port)
+{
+	return (pio_read_8(port + 5) & 0x20) != 0;
+}
+
+/** Write one character on the serial port.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @param c		The character to be written to the serial port device.
+ */
+static void ns8250_write_8(ioport8_t *port, uint8_t c)
+{
+	while (!is_transmit_empty(port))
+		;
+	
+	pio_write_8(port, c);
+}
+
+/** Read data from the serial port device.
+ *
+ * @param fun		The serial port function
+ * @param buf		The ouput buffer for read data.
+ * @param count		The number of bytes to be read.
+ *
+ * @return		The number of bytes actually read on success, negative
+ *			error number otherwise.
+ */
+static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
+{
+	ns8250_t *ns = NS8250(fun);
+	int ret = EOK;
+	
+	fibril_mutex_lock(&ns->mutex);
+	while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
+		buf[ret] = (char)buf_pop_front(&ns->input_buffer);
+		ret++;
+	}
+	fibril_mutex_unlock(&ns->mutex);
+	
+	return ret;
+}
+
+/** Write a character to the serial port.
+ *
+ * @param ns		Serial port device
+ * @param c		The character to be written
+ */
+static inline void ns8250_putchar(ns8250_t *ns, uint8_t c)
+{
+	fibril_mutex_lock(&ns->mutex);
+	ns8250_write_8(ns->port, c);
+	fibril_mutex_unlock(&ns->mutex);
+}
+
+/** Write data to the serial port.
+ *
+ * @param fun		The serial port function
+ * @param buf		The data to be written
+ * @param count		The number of bytes to be written
+ * @return		Zero on success
+ */
+static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
+{
+	ns8250_t *ns = NS8250(fun);
+	size_t idx;
+	
+	for (idx = 0; idx < count; idx++)
+		ns8250_putchar(ns, (uint8_t) buf[idx]);
+	
+	return 0;
+}
+
+static ddf_dev_ops_t ns8250_dev_ops;
+
+/** The character interface's callbacks. */
+static char_dev_ops_t ns8250_char_dev_ops = {
+	.read = &ns8250_read,
+	.write = &ns8250_write
+};
+
+static int ns8250_add_device(ddf_dev_t *dev);
+
+/** The serial port device driver's standard operations. */
+static driver_ops_t ns8250_ops = {
+	.add_device = &ns8250_add_device
+};
+
+/** The serial port device driver structure. */
+static driver_t ns8250_driver = {
+	.name = NAME,
+	.driver_ops = &ns8250_ops
+};
+
+/** Clean up the serial port soft-state
+ *
+ * @param ns		Serial port device
+ */
+static void ns8250_dev_cleanup(ns8250_t *ns)
+{
+	if (ns->dev->parent_sess) {
+		async_hangup(ns->dev->parent_sess);
+		ns->dev->parent_sess = NULL;
+	}
+}
+
+/** Enable the i/o ports of the device.
+ *
+ * @param ns		Serial port device
+ * @return		True on success, false otherwise
+ */
+static bool ns8250_pio_enable(ns8250_t *ns)
+{
+	ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ns->dev->name);
+	
+	/* Gain control over port's registers. */
+	if (pio_enable((void *)(uintptr_t) ns->io_addr, REG_COUNT,
+	    (void **) &ns->port)) {
+		ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
+		    " for device %s.", ns->io_addr, ns->dev->name);
+		return false;
+	}
+	
+	return true;
+}
+
+/** Probe the serial port device for its presence.
+ *
+ * @param ns		Serial port device
+ * @return		True if the device is present, false otherwise
+ */
+static bool ns8250_dev_probe(ns8250_t *ns)
+{
+	ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name);
+	
+	ioport8_t *port_addr = ns->port;
+	bool res = true;
+	uint8_t olddata;
+	
+	olddata = pio_read_8(port_addr + 4);
+	
+	pio_write_8(port_addr + 4, 0x10);
+	if (pio_read_8(port_addr + 6) & 0xf0)
+		res = false;
+	
+	pio_write_8(port_addr + 4, 0x1f);
+	if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0)
+		res = false;
+	
+	pio_write_8(port_addr + 4, olddata);
+	
+	if (!res) {
+		ddf_msg(LVL_DEBUG, "Device %s is not present.",
+		    ns->dev->name);
+	}
+	
+	return res;
+}
+
+/** Initialize serial port device.
+ *
+ * @param ns		Serial port device
+ * @return		Zero on success, negative error number otherwise
+ */
+static int ns8250_dev_initialize(ns8250_t *ns)
+{
+	ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ns->dev->name);
+	
+	int ret = EOK;
+	
+	hw_resource_list_t hw_resources;
+	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
+	
+	/* Connect to the parent's driver. */
+	ns->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ns->dev->handle, IPC_FLAG_BLOCKING);
+	if (!ns->dev->parent_sess) {
+		ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
+		    "device %s.", ns->dev->name);
+		ret = ENOENT;
+		goto failed;
+	}
+	
+	/* Get hw resources. */
+	ret = hw_res_get_resource_list(ns->dev->parent_sess, &hw_resources);
+	if (ret != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to get HW resources for device "
+		    "%s.", ns->dev->name);
+		goto failed;
+	}
+	
+	size_t i;
+	hw_resource_t *res;
+	bool irq = false;
+	bool ioport = false;
+	
+	for (i = 0; i < hw_resources.count; i++) {
+		res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			ns->irq = res->res.interrupt.irq;
+			irq = true;
+			ddf_msg(LVL_NOTE, "Device %s was asigned irq = 0x%x.",
+			    ns->dev->name, ns->irq);
+			break;
+			
+		case IO_RANGE:
+			ns->io_addr = res->res.io_range.address;
+			if (res->res.io_range.size < REG_COUNT) {
+				ddf_msg(LVL_ERROR, "I/O range assigned to "
+				    "device %s is too small.", ns->dev->name);
+				ret = ELIMIT;
+				goto failed;
+			}
+			ioport = true;
+			ddf_msg(LVL_NOTE, "Device %s was asigned I/O address = "
+			    "0x%x.", ns->dev->name, ns->io_addr);
+    			break;
+			
+		default:
+			break;
+		}
+	}
+	
+	if (!irq || !ioport) {
+		ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.",
+		    ns->dev->name);
+		ret = ENOENT;
+		goto failed;
+	}
+	
+	hw_res_clean_resource_list(&hw_resources);
+	return ret;
+	
+failed:
+	ns8250_dev_cleanup(ns);
+	hw_res_clean_resource_list(&hw_resources);
+	return ret;
+}
+
+/** Enable interrupts on the serial port device.
+ *
+ * Interrupt when data is received
+ *
+ * @param port		The base address of the serial port device's ports.
+ */
+static inline void ns8250_port_interrupts_enable(ioport8_t *port)
+{
+	pio_write_8(port + 1, 0x1);	/* Interrupt when data received. */
+	pio_write_8(port + 4, 0xB);
+}
+
+/** Disable interrupts on the serial port device.
+ *
+ * @param port		The base address of the serial port device's ports
+ */
+static inline void ns8250_port_interrupts_disable(ioport8_t *port)
+{
+	pio_write_8(port + 1, 0x0);	/* Disable all interrupts. */
+}
+
+/** Enable interrupts for the serial port device.
+ *
+ * @param ns		Serial port device
+ * @return		Zero on success, negative error number otherwise
+ */
+static int ns8250_interrupt_enable(ns8250_t *ns)
+{
+	/* Enable interrupt on the serial port. */
+	ns8250_port_interrupts_enable(ns->port);
+	
+	return EOK;
+}
+
+/** Set Divisor Latch Access Bit.
+ *
+ * When the Divisor Latch Access Bit is set, it is possible to set baud rate of
+ * the serial port device.
+ *
+ * @param port		The base address of the serial port device's ports.
+ */
+static inline void enable_dlab(ioport8_t *port)
+{
+	uint8_t val = pio_read_8(port + 3);
+	pio_write_8(port + 3, val | DLAB_MASK);
+}
+
+/** Clear Divisor Latch Access Bit.
+ *
+ * @param port		The base address of the serial port device's ports.
+ */
+static inline void clear_dlab(ioport8_t *port)
+{
+	uint8_t val = pio_read_8(port + 3);
+	pio_write_8(port + 3, val & (~DLAB_MASK));
+}
+
+/** Set baud rate of the serial communication on the serial device.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @param baud_rate	The baud rate to be used by the device.
+ * @return		Zero on success, negative error number otherwise (EINVAL
+ *			if the specified baud_rate is not valid).
+ */
+static int ns8250_port_set_baud_rate(ioport8_t *port, unsigned int baud_rate)
+{
+	uint16_t divisor;
+	uint8_t div_low, div_high;
+	
+	if (baud_rate < 50 || MAX_BAUD_RATE % baud_rate != 0) {
+		ddf_msg(LVL_ERROR, "Invalid baud rate %d requested.",
+		    baud_rate);
+		return EINVAL;
+	}
+	
+	divisor = MAX_BAUD_RATE / baud_rate;
+	div_low = (uint8_t)divisor;
+	div_high = (uint8_t)(divisor >> 8);
+	
+	/* Enable DLAB to be able to access baud rate divisor. */
+	enable_dlab(port);
+	
+	/* Set divisor low byte. */
+	pio_write_8(port + 0, div_low);
+	/* Set divisor high byte. */
+	pio_write_8(port + 1, div_high);
+	
+	clear_dlab(port);
+	
+	return EOK;
+}
+
+/** Get baud rate used by the serial port device.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @param baud_rate	The ouput parameter to which the baud rate is stored.
+ */
+static unsigned int ns8250_port_get_baud_rate(ioport8_t *port)
+{
+	uint16_t divisor;
+	uint8_t div_low, div_high;
+	
+	/* Enable DLAB to be able to access baud rate divisor. */
+	enable_dlab(port);
+	
+	/* Get divisor low byte. */
+	div_low = pio_read_8(port + 0);
+	/* Get divisor high byte. */
+	div_high = pio_read_8(port + 1);
+	
+	clear_dlab(port);
+	
+	divisor = (div_high << 8) | div_low;
+	return MAX_BAUD_RATE / divisor;
+}
+
+/** Get the parameters of the serial communication set on the serial port
+ * device.
+ *
+ * @param parity	The parity used.
+ * @param word_length	The length of one data unit in bits.
+ * @param stop_bits	The number of stop bits used (one or two).
+ */
+static void ns8250_port_get_com_props(ioport8_t *port, unsigned int *parity,
+    unsigned int *word_length, unsigned int *stop_bits)
+{
+	uint8_t val;
+	
+	val = pio_read_8(port + 3);
+	*parity = ((val >> 3) & 7);
+	
+	switch (val & 3) {
+	case WORD_LENGTH_5:
+		*word_length = 5;
+		break;
+	case WORD_LENGTH_6:
+		*word_length = 6;
+		break;
+	case WORD_LENGTH_7:
+		*word_length = 7;
+		break;
+	case WORD_LENGTH_8:
+		*word_length = 8;
+		break;
+	}
+	
+	if ((val >> 2) & 1)
+		*stop_bits = 2;
+	else
+		*stop_bits = 1;
+}
+
+/** Set the parameters of the serial communication on the serial port device.
+ *
+ * @param parity	The parity to be used.
+ * @param word_length	The length of one data unit in bits.
+ * @param stop_bits	The number of stop bits used (one or two).
+ * @return		Zero on success, EINVAL if some of the specified values
+ *			is invalid.
+ */
+static int ns8250_port_set_com_props(ioport8_t *port, unsigned int parity,
+    unsigned int word_length, unsigned int stop_bits)
+{
+	uint8_t val;
+	
+	switch (word_length) {
+	case 5:
+		val = WORD_LENGTH_5;
+		break;
+	case 6:
+		val = WORD_LENGTH_6;
+		break;
+	case 7:
+		val = WORD_LENGTH_7;
+		break;
+	case 8:
+		val = WORD_LENGTH_8;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	switch (stop_bits) {
+	case 1:
+		val |= ONE_STOP_BIT << 2;
+		break;
+	case 2:
+		val |= TWO_STOP_BITS << 2;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	switch (parity) {
+	case SERIAL_NO_PARITY:
+	case SERIAL_ODD_PARITY:
+	case SERIAL_EVEN_PARITY:
+	case SERIAL_MARK_PARITY:
+	case SERIAL_SPACE_PARITY:
+		val |= parity << 3;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	pio_write_8(port + 3, val);
+	
+	return EOK;
+}
+
+/** Initialize the serial port device.
+ *
+ * Set the default parameters of the serial communication.
+ *
+ * @param ns		Serial port device
+ */
+static void ns8250_initialize_port(ns8250_t *ns)
+{
+	ioport8_t *port = ns->port;
+	
+	/* Disable interrupts. */
+	ns8250_port_interrupts_disable(port);
+	/* Set baud rate. */
+	ns8250_port_set_baud_rate(port, 38400);
+	/* 8 bits, no parity, two stop bits. */
+	ns8250_port_set_com_props(port, SERIAL_NO_PARITY, 8, 2);
+	/* Enable FIFO, clear them, with 14-byte threshold. */
+	pio_write_8(port + 2, 0xC7);
+	/*
+	 * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
+	 * Aux Output2 set - needed for interrupts.
+	 */
+	pio_write_8(port + 4, 0x0B);
+}
+
+/** Read the data from the serial port device and store them to the input
+ * buffer.
+ *
+ * @param ns		Serial port device
+ */
+static void ns8250_read_from_device(ns8250_t *ns)
+{
+	ioport8_t *port = ns->port;
+	bool cont = true;
+	
+	while (cont) {
+		fibril_mutex_lock(&ns->mutex);
+		
+		cont = ns8250_received(port);
+		if (cont) {
+			uint8_t val = ns8250_read_8(port);
+			
+			if (ns->client_connected) {
+				if (!buf_push_back(&ns->input_buffer, val)) {
+					ddf_msg(LVL_WARN, "Buffer overflow on "
+					    "%s.", ns->dev->name);
+				} else {
+					ddf_msg(LVL_DEBUG2, "Character %c saved "
+					    "to the buffer of %s.",
+					    val, ns->dev->name);
+				}
+			}
+		}
+		
+		fibril_mutex_unlock(&ns->mutex);
+		fibril_yield();
+	}
+}
+
+/** The interrupt handler.
+ *
+ * The serial port is initialized to interrupt when some data come, so the
+ * interrupt is handled by reading the incomming data.
+ *
+ * @param dev		The serial port device.
+ */
+static inline void ns8250_interrupt_handler(ddf_dev_t *dev, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ns8250_read_from_device(NS8250_FROM_DEV(dev));
+}
+
+/** Register the interrupt handler for the device.
+ *
+ * @param ns		Serial port device
+ */
+static inline int ns8250_register_interrupt_handler(ns8250_t *ns)
+{
+	return register_interrupt_handler(ns->dev, ns->irq,
+	    ns8250_interrupt_handler, NULL);
+}
+
+/** Unregister the interrupt handler for the device.
+ *
+ * @param ns		Serial port device
+ */
+static inline int ns8250_unregister_interrupt_handler(ns8250_t *ns)
+{
+	return unregister_interrupt_handler(ns->dev, ns->irq);
+}
+
+/** The add_device callback method of the serial port driver.
+ *
+ * Probe and initialize the newly added device.
+ *
+ * @param dev		The serial port device.
+ */
+static int ns8250_add_device(ddf_dev_t *dev)
+{
+	ns8250_t *ns = NULL;
+	ddf_fun_t *fun = NULL;
+	bool need_cleanup = false;
+	int rc;
+	
+	ddf_msg(LVL_DEBUG, "ns8250_add_device %s (handle = %d)",
+	    dev->name, (int) dev->handle);
+	
+	/* Allocate soft-state for the device */
+	ns = ns8250_new();
+	if (ns == NULL) {
+		rc = ENOMEM;
+		goto fail;
+	}
+	
+	ns->dev = dev;
+	dev->driver_data = ns;
+	
+	rc = ns8250_dev_initialize(ns);
+	if (rc != EOK)
+		goto fail;
+	
+	need_cleanup = true;
+	
+	if (!ns8250_pio_enable(ns)) {
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
+	
+	/* Find out whether the device is present. */
+	if (!ns8250_dev_probe(ns)) {
+		rc = ENOENT;
+		goto fail;
+	}
+	
+	/* Serial port initialization (baud rate etc.). */
+	ns8250_initialize_port(ns);
+	
+	/* Register interrupt handler. */
+	if (ns8250_register_interrupt_handler(ns) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to register interrupt handler.");
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
+	
+	/* Enable interrupt. */
+	rc = ns8250_interrupt_enable(ns);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to enable the interrupt. Error code = "
+		    "%d.", rc);
+		goto fail;
+	}
+	
+	fun = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function.");
+		goto fail;
+	}
+	
+	/* Set device operations. */
+	fun->ops = &ns8250_dev_ops;
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function.");
+		goto fail;
+	}
+
+	ns->fun = fun;
+	
+	ddf_fun_add_to_class(fun, "serial");
+	
+	ddf_msg(LVL_NOTE, "Device %s successfully initialized.",
+	    dev->name);
+	
+	return EOK;
+fail:
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	if (need_cleanup)
+		ns8250_dev_cleanup(ns);
+	if (ns != NULL)
+		ns8250_delete(ns);
+	return rc;
+}
+
+/** Open the device.
+ *
+ * This is a callback function called when a client tries to connect to the
+ * device.
+ *
+ * @param dev		The device.
+ */
+static int ns8250_open(ddf_fun_t *fun)
+{
+	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
+	int res;
+	
+	fibril_mutex_lock(&data->mutex);
+	if (data->client_connected) {
+		res = ELIMIT;
+	} else {
+		res = EOK;
+		data->client_connected = true;
+	}
+	fibril_mutex_unlock(&data->mutex);
+	
+	return res;
+}
+
+/** Close the device.
+ *
+ * This is a callback function called when a client tries to disconnect from
+ * the device.
+ *
+ * @param dev		The device.
+ */
+static void ns8250_close(ddf_fun_t *fun)
+{
+	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
+	
+	fibril_mutex_lock(&data->mutex);
+	
+	assert(data->client_connected);
+	
+	data->client_connected = false;
+	buf_clear(&data->input_buffer);
+	
+	fibril_mutex_unlock(&data->mutex);
+}
+
+/** Get parameters of the serial communication which are set to the specified
+ * device.
+ *
+ * @param dev		The serial port device.
+ * @param baud_rate	The baud rate used by the device.
+ * @param parity	The type of parity used by the device.
+ * @param word_length	The size of one data unit in bits.
+ * @param stop_bits	The number of stop bits used.
+ */
+static void
+ns8250_get_props(ddf_dev_t *dev, unsigned int *baud_rate, unsigned int *parity,
+    unsigned int *word_length, unsigned int* stop_bits)
+{
+	ns8250_t *data = (ns8250_t *) dev->driver_data;
+	ioport8_t *port = data->port;
+	
+	fibril_mutex_lock(&data->mutex);
+	ns8250_port_interrupts_disable(port);
+	*baud_rate = ns8250_port_get_baud_rate(port);
+	ns8250_port_get_com_props(port, parity, word_length, stop_bits);
+	ns8250_port_interrupts_enable(port);
+	fibril_mutex_unlock(&data->mutex);
+	
+	ddf_msg(LVL_DEBUG, "ns8250_get_props: baud rate %d, parity 0x%x, word "
+	    "length %d, stop bits %d", *baud_rate, *parity, *word_length,
+	    *stop_bits);
+}
+
+/** Set parameters of the serial communication to the specified serial port
+ * device.
+ *
+ * @param dev		The serial port device.
+ * @param baud_rate	The baud rate to be used by the device.
+ * @param parity	The type of parity to be used by the device.
+ * @param word_length	The size of one data unit in bits.
+ * @param stop_bits	The number of stop bits to be used.
+ */
+static int ns8250_set_props(ddf_dev_t *dev, unsigned int baud_rate,
+    unsigned int parity, unsigned int word_length, unsigned int stop_bits)
+{
+	ddf_msg(LVL_DEBUG, "ns8250_set_props: baud rate %d, parity 0x%x, word "
+	    "length %d, stop bits %d", baud_rate, parity, word_length,
+	    stop_bits);
+	
+	ns8250_t *data = (ns8250_t *) dev->driver_data;
+	ioport8_t *port = data->port;
+	int ret;
+	
+	fibril_mutex_lock(&data->mutex);
+	ns8250_port_interrupts_disable(port);
+	ret = ns8250_port_set_baud_rate(port, baud_rate);
+	if (ret == EOK)
+		ret = ns8250_port_set_com_props(port, parity, word_length, stop_bits);
+	ns8250_port_interrupts_enable(port);
+	fibril_mutex_unlock(&data->mutex);
+	
+	return ret;
+}
+
+/** Default handler for client requests which are not handled by the standard
+ * interfaces.
+ *
+ * Configure the parameters of the serial communication.
+ */
+static void ns8250_default_handler(ddf_fun_t *fun, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*call);
+	int ret;
+	unsigned int baud_rate, parity, word_length, stop_bits;
+	
+	switch (method) {
+	case SERIAL_GET_COM_PROPS:
+		ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
+		    &stop_bits);
+		async_answer_4(callid, EOK, baud_rate, parity, word_length,
+		    stop_bits);
+		break;
+		
+	case SERIAL_SET_COM_PROPS:
+ 		baud_rate = IPC_GET_ARG1(*call);
+		parity = IPC_GET_ARG2(*call);
+		word_length = IPC_GET_ARG3(*call);
+		stop_bits = IPC_GET_ARG4(*call);
+		ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
+		    stop_bits);
+		async_answer_0(callid, ret);
+		break;
+		
+	default:
+		async_answer_0(callid, ENOTSUP);
+	}
+}
+
+/** Initialize the serial port driver.
+ *
+ * Initialize device operations structures with callback methods for handling
+ * client requests to the serial port devices.
+ */
+static void ns8250_init(void)
+{
+	ddf_log_init(NAME, LVL_ERROR);
+	
+	ns8250_dev_ops.open = &ns8250_open;
+	ns8250_dev_ops.close = &ns8250_close;
+	
+	ns8250_dev_ops.interfaces[CHAR_DEV_IFACE] = &ns8250_char_dev_ops;
+	ns8250_dev_ops.default_handler = &ns8250_default_handler;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS serial port driver\n");
+	ns8250_init();
+	return ddf_driver_main(&ns8250_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/char/ns8250/ns8250.ma
===================================================================
--- uspace/drv/char/ns8250/ns8250.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/char/ns8250/ns8250.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 isa/ns8250
Index: pace/drv/ehci_hcd/Makefile
===================================================================
--- uspace/drv/ehci_hcd/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,47 +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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBHOST_PREFIX)/libusbhost.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBHOST_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = ehci_hcd
-
-SOURCES = \
-	hc_iface.c \
-	main.c \
-	pci.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/ehci_hcd/ehci.h
===================================================================
--- uspace/drv/ehci_hcd/ehci.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * 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 drvusbehci
- * @{
- */
-/** @file
- * Common EHCI definitions.
- */
-#ifndef DRV_EHCI_EHCI_H
-#define DRV_EHCI_EHCI_H
-
-#include <usbhc_iface.h>
-
-#define NAME "ehci_hcd"
-
-extern usbhc_iface_t ehci_hc_iface;
-
-#endif
-/**
- * @}
- */
-
Index: pace/drv/ehci_hcd/ehci_hcd.ma
===================================================================
--- uspace/drv/ehci_hcd/ehci_hcd.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,39 +1,0 @@
-10 pci/ven=1002&dev=4345
-10 pci/ven=1002&dev=4386
-10 pci/ven=1002&dev=4396
-10 pci/ven=1002&dev=4373
-10 pci/ven=1022&dev=7463
-10 pci/ven=1022&dev=7808
-10 pci/ven=102f&dev=01b5
-10 pci/ven=10cf&dev=1415
-10 pci/ven=10de&dev=00e8
-10 pci/ven=10de&dev=055f
-10 pci/ven=10de&dev=056a
-10 pci/ven=10de&dev=077c
-10 pci/ven=10de&dev=077e
-10 pci/ven=10de&dev=0aa6
-10 pci/ven=10de&dev=0aa9
-10 pci/ven=10de&dev=0aaa
-10 pci/ven=10de&dev=0d9d
-10 pci/ven=1166&dev=0414
-10 pci/ven=1166&dev=0416
-10 pci/ven=1414&dev=5805
-10 pci/ven=1414&dev=5807
-10 pci/ven=15ad&dev=0770
-10 pci/ven=17a0&dev=8084
-10 pci/ven=8086&dev=24cd
-10 pci/ven=8086&dev=24dd
-10 pci/ven=8086&dev=265c
-10 pci/ven=8086&dev=268c
-10 pci/ven=8086&dev=27cc
-10 pci/ven=8086&dev=2836
-10 pci/ven=8086&dev=283a
-10 pci/ven=8086&dev=293a
-10 pci/ven=8086&dev=293c
-10 pci/ven=8086&dev=3a3a
-10 pci/ven=8086&dev=3a3c
-10 pci/ven=8086&dev=3a6a
-10 pci/ven=8086&dev=3a6c
-10 pci/ven=8086&dev=8117
-10 pci/ven=8086&dev=8807
-10 pci/ven=8086&dev=880f
Index: pace/drv/ehci_hcd/hc_iface.c
===================================================================
--- uspace/drv/ehci_hcd/hc_iface.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,326 +1,0 @@
-/*
- * 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 drvusbehci
- * @{
- */
-/** @file
- * USB-HC interface implementation.
- */
-#include <ddf/driver.h>
-#include <ddf/interrupt.h>
-#include <device/hw_res.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
-#include <usb/debug.h>
-
-#include "ehci.h"
-
-#define UNSUPPORTED(methodname) \
-	usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
-	    methodname, __FILE__, __LINE__)
-
-/** Found free USB address.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] speed Speed of the device that will get this address.
- * @param[out] address Non-null pointer where to store the free address.
- * @return Error code.
- */
-static int request_address(ddf_fun_t *fun, usb_speed_t speed,
-    usb_address_t *address)
-{
-	UNSUPPORTED("request_address");
-
-	return ENOTSUP;
-}
-
-/** Bind USB address with device devman handle.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address of the device.
- * @param[in] handle Devman handle of the device.
- * @return Error code.
- */
-static int bind_address(ddf_fun_t *fun,
-    usb_address_t address, devman_handle_t handle)
-{
-	UNSUPPORTED("bind_address");
-
-	return ENOTSUP;
-}
-
-/** Find device handle by USB address.
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address Address in question.
- * @param[out] handle Where to store device handle if found.
- * @return Error code.
- */
-static int find_by_address(ddf_fun_t *fun, usb_address_t address,
-    devman_handle_t *handle)
-{
-	UNSUPPORTED("find_by_address");
-
-	return ENOTSUP;
-}
-
-/** Release previously requested address.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address to be released.
- * @return Error code.
- */
-static int release_address(ddf_fun_t *fun, usb_address_t address)
-{
-	UNSUPPORTED("release_address");
-
-	return ENOTSUP;
-}
-
-/** Register endpoint for bandwidth reservation.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address of the device.
- * @param[in] speed Endpoint speed (invalid means to use device one).
- * @param[in] endpoint Endpoint number.
- * @param[in] transfer_type USB transfer type.
- * @param[in] direction Endpoint data direction.
- * @param[in] max_packet_size Max packet size of the endpoint.
- * @param[in] interval Polling interval.
- * @return Error code.
- */
-static int register_endpoint(ddf_fun_t *fun,
-    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
-    usb_transfer_type_t transfer_type, usb_direction_t direction,
-    size_t max_packet_size, unsigned int interval)
-{
-	UNSUPPORTED("register_endpoint");
-
-	return ENOTSUP;
-}
-
-/** Unregister endpoint (free some bandwidth reservation).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address of the device.
- * @param[in] endpoint Endpoint number.
- * @param[in] direction Endpoint data direction.
- * @return Error code.
- */
-static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction)
-{
-	UNSUPPORTED("unregister_endpoint");
-
-	return ENOTSUP;
-}
-
-/** Schedule interrupt out transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
- *	by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	UNSUPPORTED("interrupt_out");
-
-	return ENOTSUP;
-}
-
-/** Schedule interrupt in transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	UNSUPPORTED("interrupt_in");
-
-	return ENOTSUP;
-}
-
-/** Schedule bulk out transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
- *	by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int bulk_out(ddf_fun_t *fun, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	UNSUPPORTED("bulk_out");
-
-	return ENOTSUP;
-}
-
-/** Schedule bulk in transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int bulk_in(ddf_fun_t *fun, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	UNSUPPORTED("bulk_in");
-
-	return ENOTSUP;
-}
-
-/** Schedule control write transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
- *	and deallocated by the caller).
- * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
- * @param[in] data_buffer Data buffer (in USB endianess, allocated and
- *	deallocated by the caller).
- * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int control_write(ddf_fun_t *fun, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *data_buffer, size_t data_buffer_size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	UNSUPPORTED("control_write");
-
-	return ENOTSUP;
-}
-
-/** Schedule control read transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
- *	and deallocated by the caller).
- * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
- * @param[in] data_buffer Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int control_read(ddf_fun_t *fun, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *data_buffer, size_t data_buffer_size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	UNSUPPORTED("control_read");
-
-	return ENOTSUP;
-}
-
-/** Host controller interface implementation for EHCI. */
-usbhc_iface_t ehci_hc_iface = {
-	.request_address = request_address,
-	.bind_address = bind_address,
-	.find_by_address = find_by_address,
-	.release_address = release_address,
-
-	.register_endpoint = register_endpoint,
-	.unregister_endpoint = unregister_endpoint,
-
-	.interrupt_out = interrupt_out,
-	.interrupt_in = interrupt_in,
-
-	.bulk_out = bulk_out,
-	.bulk_in = bulk_in,
-
-	.control_write = control_write,
-	.control_read = control_read
-};
-
-/**
- * @}
- */
Index: pace/drv/ehci_hcd/main.c
===================================================================
--- uspace/drv/ehci_hcd/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * 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 drvusbehci
- * @{
- */
-/** @file
- * Main routines of EHCI driver.
- */
-#include <ddf/driver.h>
-#include <ddf/interrupt.h>
-#include <device/hw_res.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
-#include <usb/debug.h>
-
-#include "pci.h"
-#include "ehci.h"
-
-static int ehci_add_device(ddf_dev_t *device);
-/*----------------------------------------------------------------------------*/
-static driver_ops_t ehci_driver_ops = {
-	.add_device = ehci_add_device,
-};
-/*----------------------------------------------------------------------------*/
-static driver_t ehci_driver = {
-	.name = NAME,
-	.driver_ops = &ehci_driver_ops
-};
-static ddf_dev_ops_t hc_ops = {
-	.interfaces[USBHC_DEV_IFACE] = &ehci_hc_iface,
-};
-
-/*----------------------------------------------------------------------------*/
-/** Initializes a new ddf driver instance of EHCI hcd.
- *
- * @param[in] device DDF instance of the device to initialize.
- * @return Error code.
- */
-static int ehci_add_device(ddf_dev_t *device)
-{
-	assert(device);
-#define CHECK_RET_RETURN(ret, message...) \
-if (ret != EOK) { \
-	usb_log_error(message); \
-	return ret; \
-}
-
-	uintptr_t reg_base = 0;
-	size_t reg_size = 0;
-	int irq = 0;
-
-	int ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
-	CHECK_RET_RETURN(ret,
-	    "Failed to get memory addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
-	usb_log_info("Memory mapped regs at 0x%" PRIxn " (size %zu), IRQ %d.\n",
-	    reg_base, reg_size, irq);
-
-	ret = pci_disable_legacy(device, reg_base, reg_size, irq);
-	CHECK_RET_RETURN(ret,
-	    "Failed to disable legacy USB: %s.\n", str_error(ret));
-
-	ddf_fun_t *hc_fun = ddf_fun_create(device, fun_exposed, "ehci_hc");
-	if (hc_fun == NULL) {
-		usb_log_error("Failed to create EHCI function.\n");
-		return ENOMEM;
-	}
-	hc_fun->ops = &hc_ops;
-
-	ret = ddf_fun_bind(hc_fun);
-	CHECK_RET_RETURN(ret,
-	    "Failed to bind EHCI function: %s.\n",
-	    str_error(ret));
-	ret = ddf_fun_add_to_class(hc_fun, USB_HC_DDF_CLASS_NAME);
-	CHECK_RET_RETURN(ret,
-	    "Failed to add EHCI to HC class: %s.\n",
-	    str_error(ret));
-
-	usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",
-	    device->name, device->handle);
-
-	return EOK;
-#undef CHECK_RET_RETURN
-}
-/*----------------------------------------------------------------------------*/
-/** Initializes global driver structures (NONE).
- *
- * @param[in] argc Nmber of arguments in argv vector (ignored).
- * @param[in] argv Cmdline argument vector (ignored).
- * @return Error code.
- *
- * Driver debug level is set here.
- */
-int main(int argc, char *argv[])
-{
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-	return ddf_driver_main(&ehci_driver);
-}
-/**
- * @}
- */
Index: pace/drv/ehci_hcd/pci.c
===================================================================
--- uspace/drv/ehci_hcd/pci.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,391 +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 drvusbehci
- * @{
- */
-/**
- * @file
- * PCI related functions needed by the EHCI driver.
- */
-
-#include <errno.h>
-#include <str_error.h>
-#include <assert.h>
-#include <as.h>
-#include <devman.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-#include <device/hw_res.h>
-
-#include <usb/debug.h>
-#include <pci_dev_iface.h>
-
-#include "pci.h"
-
-#define PAGE_SIZE_MASK 0xfffff000
-
-#define HCC_PARAMS_OFFSET 0x8
-#define HCC_PARAMS_EECP_MASK 0xff
-#define HCC_PARAMS_EECP_OFFSET 8
-
-#define CMD_OFFSET 0x0
-#define STS_OFFSET 0x4
-#define INT_OFFSET 0x8
-#define CFG_OFFSET 0x40
-
-#define USBCMD_RUN 1
-#define USBSTS_HALTED (1 << 12)
-
-#define USBLEGSUP_OFFSET 0
-#define USBLEGSUP_BIOS_CONTROL (1 << 16)
-#define USBLEGSUP_OS_CONTROL (1 << 24)
-#define USBLEGCTLSTS_OFFSET 4
-
-#define DEFAULT_WAIT 1000
-#define WAIT_STEP 10
-
-#define PCI_READ(size) \
-do { \
-	async_sess_t *parent_sess = \
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, \
-	    IPC_FLAG_BLOCKING); \
-	if (!parent_sess) \
-		return ENOMEM; \
-	\
-	sysarg_t add = (sysarg_t) address; \
-	sysarg_t val; \
-	\
-	async_exch_t *exch = async_exchange_begin(parent_sess); \
-	\
-	const int ret = \
-	    async_req_2_1(exch, DEV_IFACE_ID(PCI_DEV_IFACE), \
-	        IPC_M_CONFIG_SPACE_READ_##size, add, &val); \
-	\
-	async_exchange_end(exch); \
-	async_hangup(parent_sess); \
-	\
-	assert(value); \
-	\
-	*value = val; \
-	return ret; \
-} while (0)
-
-static int pci_read32(const ddf_dev_t *dev, int address, uint32_t *value)
-{
-	PCI_READ(32);
-}
-
-static int pci_read16(const ddf_dev_t *dev, int address, uint16_t *value)
-{
-	PCI_READ(16);
-}
-
-static int pci_read8(const ddf_dev_t *dev, int address, uint8_t *value)
-{
-	PCI_READ(8);
-}
-
-#define PCI_WRITE(size) \
-do { \
-	async_sess_t *parent_sess = \
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, \
-	    IPC_FLAG_BLOCKING); \
-	if (!parent_sess) \
-		return ENOMEM; \
-	\
-	sysarg_t add = (sysarg_t) address; \
-	sysarg_t val = value; \
-	\
-	async_exch_t *exch = async_exchange_begin(parent_sess); \
-	\
-	const int ret = \
-	    async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE), \
-	        IPC_M_CONFIG_SPACE_WRITE_##size, add, val); \
-	\
-	async_exchange_end(exch); \
-	async_hangup(parent_sess); \
-	\
-	return ret; \
-} while(0)
-
-static int pci_write32(const ddf_dev_t *dev, int address, uint32_t value)
-{
-	PCI_WRITE(32);
-}
-
-static int pci_write16(const ddf_dev_t *dev, int address, uint16_t value)
-{
-	PCI_WRITE(16);
-}
-
-static int pci_write8(const ddf_dev_t *dev, int address, uint8_t value)
-{
-	PCI_WRITE(8);
-}
-
-/** Get address of registers and IRQ for given device.
- *
- * @param[in] dev Device asking for the addresses.
- * @param[out] mem_reg_address Base address of the memory range.
- * @param[out] mem_reg_size Size of the memory range.
- * @param[out] irq_no IRQ assigned to the device.
- * @return Error code.
- */
-int pci_get_my_registers(const ddf_dev_t *dev,
-    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
-{
-	assert(dev != NULL);
-	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	hw_resource_list_t hw_resources;
-	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
-	if (rc != EOK) {
-		async_hangup(parent_sess);
-		return rc;
-	}
-	
-	uintptr_t mem_address = 0;
-	size_t mem_size = 0;
-	bool mem_found = false;
-	
-	int irq = 0;
-	bool irq_found = false;
-	
-	size_t i;
-	for (i = 0; i < hw_resources.count; i++) {
-		hw_resource_t *res = &hw_resources.resources[i];
-		switch (res->type) {
-		case INTERRUPT:
-			irq = res->res.interrupt.irq;
-			irq_found = true;
-			usb_log_debug2("Found interrupt: %d.\n", irq);
-			break;
-		case MEM_RANGE:
-			if (res->res.mem_range.address != 0
-			    && res->res.mem_range.size != 0 ) {
-				mem_address = res->res.mem_range.address;
-				mem_size = res->res.mem_range.size;
-				usb_log_debug2("Found mem: %" PRIxn" %zu.\n",
-				    mem_address, mem_size);
-				mem_found = true;
-			}
-		default:
-			break;
-		}
-	}
-	
-	if (mem_found && irq_found) {
-		*mem_reg_address = mem_address;
-		*mem_reg_size = mem_size;
-		*irq_no = irq;
-		rc = EOK;
-	} else {
-		rc = ENOENT;
-	}
-	
-	async_hangup(parent_sess);
-	return rc;
-}
-/*----------------------------------------------------------------------------*/
-/** Calls the PCI driver with a request to enable interrupts
- *
- * @param[in] device Device asking for interrupts
- * @return Error code.
- */
-int pci_enable_interrupts(const ddf_dev_t *device)
-{
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	const bool enabled = hw_res_enable_interrupt(parent_sess);
-	async_hangup(parent_sess);
-	
-	return enabled ? EOK : EIO;
-}
-/*----------------------------------------------------------------------------*/
-/** Implements BIOS handoff routine as decribed in EHCI spec
- *
- * @param[in] device Device asking for interrupts
- * @return Error code.
- */
-int pci_disable_legacy(
-    const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size, int irq)
-{
-	assert(device);
-	(void) pci_read16;
-	(void) pci_read8;
-	(void) pci_write16;
-
-#define CHECK_RET_RETURN(ret, message...) \
-	if (ret != EOK) { \
-		usb_log_error(message); \
-		return ret; \
-	} else (void)0
-
-	/* Map EHCI registers */
-	void *regs = NULL;
-	int ret = pio_enable((void*)reg_base, reg_size, &regs);
-	CHECK_RET_RETURN(ret, "Failed to map registers %p: %s.\n",
-	    (void *) reg_base, str_error(ret));
-
-	const uint32_t hcc_params =
-	    *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
-	usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
-
-	/* Read value of EHCI Extended Capabilities Pointer
-	 * position of EEC registers (points to PCI config space) */
-	const uint32_t eecp =
-	    (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
-	usb_log_debug("Value of EECP: %x.\n", eecp);
-
-	/* Read the first EEC. i.e. Legacy Support register */
-	uint32_t usblegsup;
-	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
-	CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
-	usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
-
-	/* Request control from firmware/BIOS, by writing 1 to highest byte.
-	 * (OS Control semaphore)*/
-	usb_log_debug("Requesting OS control.\n");
-	ret = pci_write8(device, eecp + USBLEGSUP_OFFSET + 3, 1);
-	CHECK_RET_RETURN(ret, "Failed to request OS EHCI control: %s.\n",
-	    str_error(ret));
-
-	size_t wait = 0;
-	/* Wait for BIOS to release control. */
-	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
-	while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
-		async_usleep(WAIT_STEP);
-		ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
-		wait += WAIT_STEP;
-	}
-
-
-	if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
-		usb_log_info("BIOS released control after %zu usec.\n", wait);
-	} else {
-		/* BIOS failed to hand over control, this should not happen. */
-		usb_log_warning( "BIOS failed to release control after "
-		    "%zu usecs, force it.\n", wait);
-		ret = pci_write32(device, eecp + USBLEGSUP_OFFSET,
-		    USBLEGSUP_OS_CONTROL);
-		CHECK_RET_RETURN(ret, "Failed to force OS control: %s.\n",
-		    str_error(ret));
-		/* Check capability type here, A value of 01h
-		 * identifies the capability as Legacy Support.
-		 * This extended capability requires one
-		 * additional 32-bit register for control/status information,
-		 * and this register is located at offset EECP+04h
-		 * */
-		if ((usblegsup & 0xff) == 1) {
-			/* Read the second EEC
-			 * Legacy Support and Control register */
-			uint32_t usblegctlsts;
-			ret = pci_read32(
-			    device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
-			CHECK_RET_RETURN(ret,
-			    "Failed to get USBLEGCTLSTS: %s.\n", str_error(ret));
-			usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n",
-			    usblegctlsts);
-			/* Zero SMI enables in legacy control register.
-			 * It should prevent pre-OS code from interfering. */
-			ret = pci_write32(device, eecp + USBLEGCTLSTS_OFFSET,
-			    0xe0000000); /* three upper bits are WC */
-			CHECK_RET_RETURN(ret,
-			    "Failed(%d) zero USBLEGCTLSTS.\n", ret);
-			udelay(10);
-			ret = pci_read32(
-			    device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
-			CHECK_RET_RETURN(ret,
-			    "Failed to get USBLEGCTLSTS 2: %s.\n",
-			    str_error(ret));
-			usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
-			    usblegctlsts);
-		}
-	}
-
-
-	/* Read again Legacy Support register */
-	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
-	CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
-	usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
-
-	/*
-	 * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT
-	 */
-
-	/* Get size of capability registers in memory space. */
-	const unsigned operation_offset = *(uint8_t*)regs;
-	usb_log_debug("USBCMD offset: %d.\n", operation_offset);
-
-	/* Zero USBCMD register. */
-	volatile uint32_t *usbcmd =
-	    (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET);
-	volatile uint32_t *usbsts =
-	    (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET);
-	volatile uint32_t *usbconf =
-	    (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET);
-	volatile uint32_t *usbint =
-	    (uint32_t*)((uint8_t*)regs + operation_offset + INT_OFFSET);
-	usb_log_debug("USBCMD value: %x.\n", *usbcmd);
-	if (*usbcmd & USBCMD_RUN) {
-		*usbsts = 0x3f; /* ack all interrupts */
-		*usbint = 0; /* disable all interrutps */
-		*usbconf = 0; /* relase control of RH ports */
-
-		*usbcmd = 0;
-		/* Wait until hc is halted */
-		while ((*usbsts & USBSTS_HALTED) == 0);
-		usb_log_info("EHCI turned off.\n");
-	} else {
-		usb_log_info("EHCI was not running.\n");
-	}
-	usb_log_debug("Registers: \n"
-	    "\t USBCMD: %x(0x00080000 = at least 1ms between interrupts)\n"
-	    "\t USBSTS: %x(0x00001000 = HC halted)\n"
-	    "\t USBINT: %x(0x0 = no interrupts).\n"
-	    "\t CONFIG: %x(0x0 = ports controlled by companion hc).\n",
-	    *usbcmd, *usbsts, *usbint, *usbconf);
-
-	return ret;
-#undef CHECK_RET_RETURN
-}
-
-/**
- * @}
- */
Index: pace/drv/ehci_hcd/pci.h
===================================================================
--- uspace/drv/ehci_hcd/pci.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * 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 drvusbehci
- * @{
- */
-/** @file
- * PCI related functions needed by EHCI driver.
- */
-#ifndef DRV_EHCI_PCI_H
-#define DRV_EHCI_PCI_H
-
-#include <ddf/driver.h>
-
-int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
-int pci_enable_interrupts(const ddf_dev_t *);
-int pci_disable_legacy(const ddf_dev_t *, uintptr_t, size_t, int);
-
-#endif
-/**
- * @}
- */
-
Index: uspace/drv/infrastructure/root/Makefile
===================================================================
--- uspace/drv/infrastructure/root/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/root/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = root
+
+SOURCES = \
+	root.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/root/root.c
===================================================================
--- uspace/drv/infrastructure/root/root.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/root/root.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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.
+ */
+
+/**
+ * @defgroup root Root device driver.
+ * @brief HelenOS root device driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <str_error.h>
+#include <ctype.h>
+#include <macros.h>
+#include <inttypes.h>
+#include <sysinfo.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <devman.h>
+#include <ipc/devman.h>
+
+#define NAME "root"
+
+#define PLATFORM_FUN_NAME "hw"
+#define PLATFORM_FUN_MATCH_ID_FMT "platform/%s"
+#define PLATFORM_FUN_MATCH_SCORE 100
+
+#define VIRTUAL_FUN_NAME "virt"
+#define VIRTUAL_FUN_MATCH_ID "rootvirt"
+#define VIRTUAL_FUN_MATCH_SCORE 100
+
+static int root_add_device(ddf_dev_t *dev);
+
+/** The root device driver's standard operations. */
+static driver_ops_t root_ops = {
+	.add_device = &root_add_device
+};
+
+/** The root device driver structure. */
+static driver_t root_driver = {
+	.name = NAME,
+	.driver_ops = &root_ops
+};
+
+/** Create the function which represents the root of virtual device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_virtual_root_fun(ddf_dev_t *dev)
+{
+	const char *name = VIRTUAL_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Adding new function for virtual devices. "
+	    "Function node is `%s' (%d %s)", name,
+	    VIRTUAL_FUN_MATCH_SCORE, VIRTUAL_FUN_MATCH_ID);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, VIRTUAL_FUN_MATCH_ID,
+	    VIRTUAL_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Create the function which represents the root of HW device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_platform_fun(ddf_dev_t *dev)
+{
+	char *match_id;
+	char *platform;
+	size_t platform_size;
+
+	const char *name = PLATFORM_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
+
+	/* Get platform name from sysinfo. */
+	platform = sysinfo_get_data("platform", &platform_size);
+	if (platform == NULL) {
+		ddf_msg(LVL_ERROR, "Failed to obtain platform name.");
+		return ENOENT;
+	}
+
+	/* Null-terminate string. */
+	platform = realloc(platform, platform_size + 1);
+	if (platform == NULL) {
+		ddf_msg(LVL_ERROR, "Memory allocation failed.");
+		return ENOMEM;
+	}
+
+	platform[platform_size] = '\0';
+
+	/* Construct match ID. */
+	if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
+		ddf_msg(LVL_ERROR, "Memory allocation failed.");
+		return ENOMEM;
+	}
+
+	/* Add function. */
+	ddf_msg(LVL_DEBUG, "Adding platform function. Function node is `%s' "
+	    " (%d %s)", PLATFORM_FUN_NAME, PLATFORM_FUN_MATCH_SCORE,
+	    match_id);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Error creating function %s", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, PLATFORM_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Get the root device.
+ *
+ * @param dev		The device which is root of the whole device tree (both
+ *			of HW and pseudo devices).
+ */
+static int root_add_device(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "root_add_device, device handle=%" PRIun,
+	    dev->handle);
+
+	/*
+	 * Register virtual devices root.
+	 * We ignore error occurrence because virtual devices shall not be
+	 * vital for the system.
+	 */
+	add_virtual_root_fun(dev);
+
+	/* Register root device's children. */
+	int res = add_platform_fun(dev);
+	if (EOK != res)
+		ddf_msg(LVL_ERROR, "Failed adding child device for platform.");
+
+	return res;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS root device driver\n");
+
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&root_driver);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/infrastructure/root/root.ma
===================================================================
--- uspace/drv/infrastructure/root/root.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/root/root.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 root
Index: uspace/drv/infrastructure/rootmac/Makefile
===================================================================
--- uspace/drv/infrastructure/rootmac/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootmac/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = rootmac
+
+SOURCES = \
+	rootmac.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/rootmac/rootmac.c
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootmac/rootmac.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup root_mac Mac platform driver.
+ * @brief HelenOS Mac platform driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <errno.h>
+#include <ops/hw_res.h>
+#include <stdio.h>
+
+#define NAME  "rootmac"
+
+/** Obtain function soft-state from DDF function node */
+#define ROOTMAC_FUN(fnode) \
+	((rootmac_fun_t *) (fnode)->driver_data)
+
+typedef struct {
+	hw_resource_list_t hw_resources;
+} rootmac_fun_t;
+
+static hw_resource_t pci_conf_regs = {
+	.type = IO_RANGE,
+	.res.io_range = {
+		.address = 0xCF8,
+		.size = 8,
+		.endianness = LITTLE_ENDIAN
+	}
+};
+
+static rootmac_fun_t pci_data = {
+	.hw_resources = {
+		1,
+		&pci_conf_regs
+	}
+};
+
+static ddf_dev_ops_t rootmac_fun_ops;
+
+static bool rootmac_add_fun(ddf_dev_t *dev, const char *name,
+    const char *str_match_id, rootmac_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
+	
+	ddf_fun_t *fnode = NULL;
+	match_id_t *match_id = NULL;
+	
+	/* Create new device. */
+	fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL)
+		goto failure;
+	
+	fnode->driver_data = fun;
+	
+	/* Initialize match id list */
+	match_id = create_match_id();
+	if (match_id == NULL)
+		goto failure;
+	
+	match_id->id = str_match_id;
+	match_id->score = 100;
+	add_match_id(&fnode->match_ids, match_id);
+	
+	/* Set provided operations to the device. */
+	fnode->ops = &rootmac_fun_ops;
+	
+	/* Register function. */
+	if (ddf_fun_bind(fnode) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
+		goto failure;
+	}
+	
+	return true;
+	
+failure:
+	if (match_id != NULL)
+		match_id->id = NULL;
+	
+	if (fnode != NULL)
+		ddf_fun_destroy(fnode);
+	
+	ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name);
+	
+	return false;
+}
+
+/** Get the root device.
+ *
+ * @param dev Device which is root of the whole device tree
+ *            (both of HW and pseudo devices).
+ *
+ * @return Zero on success, negative error number otherwise.
+ *
+ */
+static int rootmac_add_device(ddf_dev_t *dev)
+{
+	/* Register functions */
+	if (!rootmac_add_fun(dev, "pci0", "pangea_pci", &pci_data))
+		ddf_msg(LVL_ERROR, "Failed to add functions for Mac platform.");
+	
+	return EOK;
+}
+
+/** The root device driver's standard operations. */
+static driver_ops_t rootmac_ops = {
+	.add_device = &rootmac_add_device
+};
+
+/** The root device driver structure. */
+static driver_t rootmac_driver = {
+	.name = NAME,
+	.driver_ops = &rootmac_ops
+};
+
+static hw_resource_list_t *rootmac_get_resources(ddf_fun_t *fnode)
+{
+	rootmac_fun_t *fun = ROOTMAC_FUN(fnode);
+	assert(fun != NULL);
+	
+	return &fun->hw_resources;
+}
+
+static bool rootmac_enable_interrupt(ddf_fun_t *fun)
+{
+	/* TODO */
+	
+	return false;
+}
+
+static hw_res_ops_t fun_hw_res_ops = {
+	&rootmac_get_resources,
+	&rootmac_enable_interrupt
+};
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS Mac platform driver\n", NAME);
+	ddf_log_init(NAME, LVL_ERROR);
+	rootmac_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
+	return ddf_driver_main(&rootmac_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/infrastructure/rootmac/rootmac.ma
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootmac/rootmac.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 platform/mac
Index: uspace/drv/infrastructure/rootpc/Makefile
===================================================================
--- uspace/drv/infrastructure/rootpc/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootpc/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = rootpc
+
+SOURCES = \
+	rootpc.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * 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.
+ */
+
+/**
+ * @defgroup root_pc PC platform driver.
+ * @brief HelenOS PC platform driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <devman.h>
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+#include <ops/hw_res.h>
+#include <device/hw_res.h>
+
+#define NAME "rootpc"
+
+/** Obtain function soft-state from DDF function node */
+#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
+
+typedef struct rootpc_fun {
+	hw_resource_list_t hw_resources;
+} rootpc_fun_t;
+
+static int rootpc_add_device(ddf_dev_t *dev);
+static void root_pc_init(void);
+
+/** The root device driver's standard operations. */
+static driver_ops_t rootpc_ops = {
+	.add_device = &rootpc_add_device
+};
+
+/** The root device driver structure. */
+static driver_t rootpc_driver = {
+	.name = NAME,
+	.driver_ops = &rootpc_ops
+};
+
+static hw_resource_t pci_conf_regs = {
+	.type = IO_RANGE,
+	.res.io_range = {
+		.address = 0xCF8,
+		.size = 8,
+		.endianness = LITTLE_ENDIAN
+	}
+};
+
+static rootpc_fun_t pci_data = {
+	.hw_resources = {
+		1,
+		&pci_conf_regs
+	}
+};
+
+static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
+{
+	rootpc_fun_t *fun = ROOTPC_FUN(fnode);
+	
+	assert(fun != NULL);
+	return &fun->hw_resources;
+}
+
+static bool rootpc_enable_interrupt(ddf_fun_t *fun)
+{
+	/* TODO */
+	
+	return false;
+}
+
+static hw_res_ops_t fun_hw_res_ops = {
+	&rootpc_get_resources,
+	&rootpc_enable_interrupt
+};
+
+/* Initialized in root_pc_init() function. */
+static ddf_dev_ops_t rootpc_fun_ops;
+
+static bool
+rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
+    rootpc_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
+	
+	ddf_fun_t *fnode = NULL;
+	match_id_t *match_id = NULL;
+	
+	/* Create new device. */
+	fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL)
+		goto failure;
+	
+	fnode->driver_data = fun;
+	
+	/* Initialize match id list */
+	match_id = create_match_id();
+	if (match_id == NULL)
+		goto failure;
+	
+	match_id->id = str_match_id;
+	match_id->score = 100;
+	add_match_id(&fnode->match_ids, match_id);
+	
+	/* Set provided operations to the device. */
+	fnode->ops = &rootpc_fun_ops;
+	
+	/* Register function. */
+	if (ddf_fun_bind(fnode) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
+		goto failure;
+	}
+	
+	return true;
+	
+failure:
+	if (match_id != NULL)
+		match_id->id = NULL;
+	
+	if (fnode != NULL)
+		ddf_fun_destroy(fnode);
+	
+	ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name);
+	
+	return false;
+}
+
+static bool rootpc_add_functions(ddf_dev_t *dev)
+{
+	return rootpc_add_fun(dev, "pci0", "intel_pci", &pci_data);
+}
+
+/** Get the root device.
+ *
+ * @param dev		The device which is root of the whole device tree (both
+ *			of HW and pseudo devices).
+ * @return		Zero on success, negative error number otherwise.
+ */
+static int rootpc_add_device(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "rootpc_add_device, device handle = %d",
+	    (int)dev->handle);
+	
+	/* Register functions. */
+	if (!rootpc_add_functions(dev)) {
+		ddf_msg(LVL_ERROR, "Failed to add functions for PC platform.");
+	}
+	
+	return EOK;
+}
+
+static void root_pc_init(void)
+{
+	ddf_log_init(NAME, LVL_ERROR);
+	rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS PC platform driver\n");
+	root_pc_init();
+	return ddf_driver_main(&rootpc_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/infrastructure/rootpc/rootpc.ma
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootpc/rootpc.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 platform/pc
Index: uspace/drv/infrastructure/rootvirt/Makefile
===================================================================
--- uspace/drv/infrastructure/rootvirt/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootvirt/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = rootvirt
+
+SOURCES = \
+	rootvirt.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/rootvirt/devices.def
===================================================================
--- uspace/drv/infrastructure/rootvirt/devices.def	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootvirt/devices.def	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,34 @@
+/*
+ * Add list of virtual devices you want to launch driver for here.
+ *
+ * Unless the list is empty, the last item shall be followed by a comma.
+ */
+#ifdef CONFIG_TEST_DRIVERS
+{
+	.name = "test1",
+	.match_id = "virtual&test1"
+},
+{
+	.name = "test2alpha",
+	.match_id = "virtual&test2"
+},
+{
+	.name = "test2bravo",
+	.match_id = "virtual&test2"
+},
+{
+	.name = "null",
+	.match_id = "virtual&test1"
+},
+{
+	.name = "test3",
+	.match_id = "virtual&test3"
+},
+#endif
+#ifdef CONFIG_RUN_VIRTUAL_USB_HC
+/* Virtual USB host controller. */
+{
+	.name = "usbhc",
+	.match_id = "usb&hc=vhc"
+},
+#endif
Index: uspace/drv/infrastructure/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup rootvirt Root device driver for virtual devices.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#define NAME "rootvirt"
+
+/** Virtual function entry */
+typedef struct {
+	/** Function name */
+	const char *name;
+	/** Function match ID */
+	const char *match_id;
+} virtual_function_t;
+
+/** List of existing virtual functions */
+virtual_function_t virtual_functions[] = {
+#include "devices.def"
+	/* Terminating item */
+	{
+		.name = NULL,
+		.match_id = NULL
+	}
+};
+
+static int rootvirt_add_device(ddf_dev_t *dev);
+
+static driver_ops_t rootvirt_ops = {
+	.add_device = &rootvirt_add_device
+};
+
+static driver_t rootvirt_driver = {
+	.name = NAME,
+	.driver_ops = &rootvirt_ops
+};
+
+/** Add function to the virtual device.
+ *
+ * @param vdev		The virtual device
+ * @param vfun		Virtual function description
+ * @return		EOK on success or negative error code.
+ */
+static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
+{
+	ddf_fun_t *fun;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Registering function `%s' (match \"%s\")",
+	    vfun->name, vfun->match_id);
+
+	fun = ddf_fun_create(vdev, fun_inner, vfun->name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", vfun->name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    vfun->name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s",
+		    vfun->name, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	ddf_msg(LVL_NOTE, "Registered child device `%s'", vfun->name);
+	return EOK;
+}
+
+static int rootvirt_add_device(ddf_dev_t *dev)
+{
+	static int instances = 0;
+
+	/*
+	 * Allow only single instance of root virtual device.
+	 */
+	instances++;
+	if (instances > 1) {
+		return ELIMIT;
+	}
+
+	ddf_msg(LVL_DEBUG, "add_device(handle=%d)", (int)dev->handle);
+
+	/*
+	 * Go through all virtual functions and try to add them.
+	 * We silently ignore failures.
+	 */
+	virtual_function_t *vfun = virtual_functions;
+	while (vfun->name != NULL) {
+		(void) rootvirt_add_fun(dev, vfun);
+		vfun++;
+	}
+
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS virtual devices root driver\n");
+
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&rootvirt_driver);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/infrastructure/rootvirt/rootvirt.ma
===================================================================
--- uspace/drv/infrastructure/rootvirt/rootvirt.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/infrastructure/rootvirt/rootvirt.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 rootvirt
Index: pace/drv/isa/Makefile
===================================================================
--- uspace/drv/isa/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Lenka Trochtova
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = isa
-
-SOURCES = \
-	isa.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/isa/isa.c
===================================================================
--- uspace/drv/isa/isa.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,510 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
- * 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.
- */
-
-/**
- * @defgroup isa ISA bus driver.
- * @brief HelenOS ISA bus driver.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <str_error.h>
-#include <ctype.h>
-#include <macros.h>
-#include <malloc.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#include <ddf/driver.h>
-#include <ddf/log.h>
-#include <ops/hw_res.h>
-
-#include <devman.h>
-#include <ipc/devman.h>
-#include <device/hw_res.h>
-
-#define NAME "isa"
-#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
-
-/** Obtain soft-state pointer from function node pointer */
-#define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
-
-#define ISA_MAX_HW_RES 4
-
-typedef struct isa_fun {
-	ddf_fun_t *fnode;
-	hw_resource_list_t hw_resources;
-} isa_fun_t;
-
-static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
-{
-	isa_fun_t *fun = ISA_FUN(fnode);
-	assert(fun != NULL);
-
-	return &fun->hw_resources;
-}
-
-static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
-{
-	/* TODO */
-
-	return false;
-}
-
-static hw_res_ops_t isa_fun_hw_res_ops = {
-	&isa_get_fun_resources,
-	&isa_enable_fun_interrupt
-};
-
-static ddf_dev_ops_t isa_fun_ops;
-
-static int isa_add_device(ddf_dev_t *dev);
-
-/** The isa device driver's standard operations */
-static driver_ops_t isa_ops = {
-	.add_device = &isa_add_device
-};
-
-/** The isa device driver structure. */
-static driver_t isa_driver = {
-	.name = NAME,
-	.driver_ops = &isa_ops
-};
-
-static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
-{
-	isa_fun_t *fun = calloc(1, sizeof(isa_fun_t));
-	if (fun == NULL)
-		return NULL;
-
-	ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
-	if (fnode == NULL) {
-		free(fun);
-		return NULL;
-	}
-
-	fun->fnode = fnode;
-	fnode->driver_data = fun;
-	return fun;
-}
-
-static char *fun_conf_read(const char *conf_path)
-{
-	bool suc = false;
-	char *buf = NULL;
-	bool opened = false;
-	int fd;
-	size_t len = 0;
-
-	fd = open(conf_path, O_RDONLY);
-	if (fd < 0) {
-		ddf_msg(LVL_ERROR, "Unable to open %s", conf_path);
-		goto cleanup;
-	}
-
-	opened = true;
-
-	len = lseek(fd, 0, SEEK_END);
-	lseek(fd, 0, SEEK_SET);
-	if (len == 0) {
-		ddf_msg(LVL_ERROR, "Configuration file '%s' is empty.",
-		    conf_path);
-		goto cleanup;
-	}
-
-	buf = malloc(len + 1);
-	if (buf == NULL) {
-		ddf_msg(LVL_ERROR, "Memory allocation failed.");
-		goto cleanup;
-	}
-
-	if (0 >= read(fd, buf, len)) {
-		ddf_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
-		goto cleanup;
-	}
-
-	buf[len] = 0;
-
-	suc = true;
-
-cleanup:
-	if (!suc && buf != NULL) {
-		free(buf);
-		buf = NULL;
-	}
-
-	if (opened)
-		close(fd);
-
-	return buf;
-}
-
-static char *str_get_line(char *str, char **next)
-{
-	char *line = str;
-
-	if (str == NULL) {
-		*next = NULL;
-		return NULL;
-	}
-
-	while (*str != '\0' && *str != '\n') {
-		str++;
-	}
-
-	if (*str != '\0') {
-		*next = str + 1;
-	} else {
-		*next = NULL;
-	}
-
-	*str = '\0';
-	return line;
-}
-
-static bool line_empty(const char *line)
-{
-	while (line != NULL && *line != 0) {
-		if (!isspace(*line))
-			return false;
-		line++;
-	}
-
-	return true;
-}
-
-static char *get_device_name(char *line)
-{
-	/* Skip leading spaces. */
-	while (*line != '\0' && isspace(*line)) {
-		line++;
-	}
-
-	/* Get the name part of the rest of the line. */
-	strtok(line, ":");
-
-	/* Allocate output buffer. */
-	size_t size = str_size(line) + 1;
-	char *name = malloc(size);
-
-	if (name != NULL) {
-		/* Copy the result to the output buffer. */
-		str_cpy(name, size, line);
-	}
-
-	return name;
-}
-
-static inline char *skip_spaces(char *line)
-{
-	/* Skip leading spaces. */
-	while (*line != '\0' && isspace(*line))
-		line++;
-
-	return line;
-}
-
-static void isa_fun_set_irq(isa_fun_t *fun, int irq)
-{
-	size_t count = fun->hw_resources.count;
-	hw_resource_t *resources = fun->hw_resources.resources;
-
-	if (count < ISA_MAX_HW_RES) {
-		resources[count].type = INTERRUPT;
-		resources[count].res.interrupt.irq = irq;
-
-		fun->hw_resources.count++;
-
-		ddf_msg(LVL_NOTE, "Added irq 0x%x to function %s", irq,
-		    fun->fnode->name);
-	}
-}
-
-static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
-{
-	size_t count = fun->hw_resources.count;
-	hw_resource_t *resources = fun->hw_resources.resources;
-
-	if (count < ISA_MAX_HW_RES) {
-		resources[count].type = IO_RANGE;
-		resources[count].res.io_range.address = addr;
-		resources[count].res.io_range.size = len;
-		resources[count].res.io_range.endianness = LITTLE_ENDIAN;
-
-		fun->hw_resources.count++;
-
-		ddf_msg(LVL_NOTE, "Added io range (addr=0x%x, size=0x%x) to "
-		    "function %s", (unsigned int) addr, (unsigned int) len,
-		    fun->fnode->name);
-	}
-}
-
-static void fun_parse_irq(isa_fun_t *fun, char *val)
-{
-	int irq = 0;
-	char *end = NULL;
-
-	val = skip_spaces(val);
-	irq = (int)strtol(val, &end, 0x10);
-
-	if (val != end)
-		isa_fun_set_irq(fun, irq);
-}
-
-static void fun_parse_io_range(isa_fun_t *fun, char *val)
-{
-	size_t addr, len;
-	char *end = NULL;
-
-	val = skip_spaces(val);
-	addr = strtol(val, &end, 0x10);
-
-	if (val == end)
-		return;
-
-	val = skip_spaces(end);
-	len = strtol(val, &end, 0x10);
-
-	if (val == end)
-		return;
-
-	isa_fun_set_io_range(fun, addr, len);
-}
-
-static void get_match_id(char **id, char *val)
-{
-	char *end = val;
-
-	while (!isspace(*end))
-		end++;
-
-	size_t size = end - val + 1;
-	*id = (char *)malloc(size);
-	str_cpy(*id, size, val);
-}
-
-static void fun_parse_match_id(isa_fun_t *fun, char *val)
-{
-	char *id = NULL;
-	int score = 0;
-	char *end = NULL;
-	int rc;
-
-	val = skip_spaces(val);
-
-	score = (int)strtol(val, &end, 10);
-	if (val == end) {
-		ddf_msg(LVL_ERROR, "Cannot read match score for function "
-		    "%s.", fun->fnode->name);
-		return;
-	}
-
-	val = skip_spaces(end);
-	get_match_id(&id, val);
-	if (id == NULL) {
-		ddf_msg(LVL_ERROR, "Cannot read match ID for function %s.",
-		    fun->fnode->name);
-		return;
-	}
-
-	ddf_msg(LVL_DEBUG, "Adding match id '%s' with score %d to "
-	    "function %s", id, score, fun->fnode->name);
-
-	rc = ddf_fun_add_match_id(fun->fnode, id, score);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
-		    str_error(rc));
-	}
-}
-
-static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
-    void (*read_fn)(isa_fun_t *, char *))
-{
-	size_t proplen = str_size(prop);
-
-	if (str_lcmp(line, prop, proplen) == 0) {
-		line += proplen;
-		line = skip_spaces(line);
-		(*read_fn)(fun, line);
-
-		return true;
-	}
-
-	return false;
-}
-
-static void fun_prop_parse(isa_fun_t *fun, char *line)
-{
-	/* Skip leading spaces. */
-	line = skip_spaces(line);
-
-	if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
-	    !prop_parse(fun, line, "irq", &fun_parse_irq) &&
-	    !prop_parse(fun, line, "match", &fun_parse_match_id)) {
-
-		ddf_msg(LVL_ERROR, "Undefined device property at line '%s'",
-		    line);
-	}
-}
-
-static void fun_hw_res_alloc(isa_fun_t *fun)
-{
-	fun->hw_resources.resources = 
-	    (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
-}
-
-static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
-{
-	char *line;
-	char *fun_name = NULL;
-
-	/* Skip empty lines. */
-	while (true) {
-		line = str_get_line(fun_conf, &fun_conf);
-
-		if (line == NULL) {
-			/* no more lines */
-			return NULL;
-		}
-
-		if (!line_empty(line))
-			break;
-	}
-
-	/* Get device name. */
-	fun_name = get_device_name(line);
-	if (fun_name == NULL)
-		return NULL;
-
-	isa_fun_t *fun = isa_fun_create(dev, fun_name);
-	if (fun == NULL) {
-		free(fun_name);
-		return NULL;
-	}
-
-	/* Allocate buffer for the list of hardware resources of the device. */
-	fun_hw_res_alloc(fun);
-
-	/* Get properties of the device (match ids, irq and io range). */
-	while (true) {
-		line = str_get_line(fun_conf, &fun_conf);
-
-		if (line_empty(line)) {
-			/* no more device properties */
-			break;
-		}
-
-		/*
-		 * Get the device's property from the configuration line
-		 * and store it in the device structure.
-		 */
-		fun_prop_parse(fun, line);
-	}
-
-	/* Set device operations to the device. */
-	fun->fnode->ops = &isa_fun_ops;
-
-	ddf_msg(LVL_DEBUG, "Binding function %s.", fun->fnode->name);
-
-	/* XXX Handle error */
-	(void) ddf_fun_bind(fun->fnode);
-
-	return fun_conf;
-}
-
-static void fun_conf_parse(char *conf, ddf_dev_t *dev)
-{
-	while (conf != NULL && *conf != '\0') {
-		conf = isa_fun_read_info(conf, dev);
-	}
-}
-
-static void isa_functions_add(ddf_dev_t *dev)
-{
-	char *fun_conf;
-
-	fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
-	if (fun_conf != NULL) {
-		fun_conf_parse(fun_conf, dev);
-		free(fun_conf);
-	}
-}
-
-static int isa_add_device(ddf_dev_t *dev)
-{
-	ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d",
-	    (int) dev->handle);
-
-	/* Make the bus device more visible. Does not do anything. */
-	ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
-
-	ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
-	if (ctl == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating control function.");
-		return EXDEV;
-	}
-
-	if (ddf_fun_bind(ctl) != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding control function.");
-		return EXDEV;
-	}
-
-	/* Add functions as specified in the configuration file. */
-	isa_functions_add(dev);
-	ddf_msg(LVL_NOTE, "Finished enumerating legacy functions");
-
-	return EOK;
-}
-
-static void isa_init() 
-{
-	ddf_log_init(NAME, LVL_ERROR);
-	isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS ISA bus driver\n");
-	isa_init();
-	return ddf_driver_main(&isa_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/isa/isa.dev
===================================================================
--- uspace/drv/isa/isa.dev	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,15 +1,0 @@
-com1:
-	match 100 isa/ns8250
-	irq 4
-	io_range 3f8 8
-
-com2:
-	match 100 isa/ns8250
-	irq 3
-	io_range 2f8 8
-
-keyboard:
-	match 100 isa/keyboard
-	irq 1
-	io_range 060 10
-	
Index: pace/drv/isa/isa.ma
===================================================================
--- uspace/drv/isa/isa.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-9 	pci/ven=8086&dev=7000
Index: pace/drv/ns8250/Makefile
===================================================================
--- uspace/drv/ns8250/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Lenka Trochtova
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = ns8250
-
-SOURCES = \
-	ns8250.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/ns8250/cyclic_buffer.h
===================================================================
--- uspace/drv/ns8250/cyclic_buffer.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,83 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * 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 ns8250
- * @{
- */
-/** @file
- */
-
-#ifndef CYCLIC_BUFFER_H_
-#define CYCLIC_BUFFER_H_
-
-#define BUF_LEN 256
-
-typedef struct cyclic_buffer {
-	uint8_t buf[BUF_LEN];
-	int start;
-	int cnt;
-}  cyclic_buffer_t;
-
-/*
- * @return		False if the buffer is full.
- */
-static inline bool buf_push_back(cyclic_buffer_t *buf, uint8_t item)
-{
-	if (buf->cnt >= BUF_LEN)
-		return false;
-	int pos = (buf->start + buf->cnt) % BUF_LEN;
-	buf->buf[pos] = item;
-	buf->cnt++;
-	return true;
-}
-
-static inline bool buf_is_empty(cyclic_buffer_t *buf)
-{
-	return buf->cnt == 0;
-}
-
-static inline uint8_t buf_pop_front(cyclic_buffer_t *buf)
-{
-	assert(!buf_is_empty(buf));
-	
-	uint8_t res = buf->buf[buf->start];
-	buf->start = (buf->start + 1) % BUF_LEN;
-	buf->cnt--;
-	return res;
-}
-
-static inline void buf_clear(cyclic_buffer_t *buf)
-{
-	buf->cnt = 0;
-}
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/ns8250/ns8250.c
===================================================================
--- uspace/drv/ns8250/ns8250.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,963 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
- * 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.
- */
-
-/**
- * @defgroup ns8250 Serial port driver.
- * @brief HelenOS serial port driver.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <ctype.h>
-#include <macros.h>
-#include <malloc.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-
-#include <ddf/driver.h>
-#include <ddf/interrupt.h>
-#include <ddf/log.h>
-#include <ops/char_dev.h>
-
-#include <devman.h>
-#include <ipc/devman.h>
-#include <device/hw_res.h>
-#include <ipc/serial_ctl.h>
-
-#include "cyclic_buffer.h"
-
-#define NAME "ns8250"
-
-#define REG_COUNT 7
-#define MAX_BAUD_RATE 115200
-#define DLAB_MASK (1 << 7)
-
-/** Obtain soft-state structure from function node */
-#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
-
-/** Obtain soft-state structure from device node */
-#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
-
-/** The number of bits of one data unit send by the serial port. */
-typedef enum {
-	WORD_LENGTH_5,
-	WORD_LENGTH_6,
-	WORD_LENGTH_7,
-	WORD_LENGTH_8
-} word_length_t;
-
-/** The number of stop bits used by the serial port. */
-typedef enum {
-	/** Use one stop bit. */
-	ONE_STOP_BIT,
-	/** 1.5 stop bits for word length 5, 2 stop bits otherwise. */
-	TWO_STOP_BITS
-} stop_bit_t;
-
-/** The driver data for the serial port devices. */
-typedef struct ns8250 {
-	/** DDF device node */
-	ddf_dev_t *dev;
-	/** DDF function node */
-	ddf_fun_t *fun;
-	/** Is there any client conntected to the device? */
-	bool client_connected;
-	/** The irq assigned to this device. */
-	int irq;
-	/** The base i/o address of the devices registers. */
-	uint32_t io_addr;
-	/** The i/o port used to access the serial ports registers. */
-	ioport8_t *port;
-	/** The buffer for incomming data. */
-	cyclic_buffer_t input_buffer;
-	/** The fibril mutex for synchronizing the access to the device. */
-	fibril_mutex_t mutex;
-} ns8250_t;
-
-/** Create per-device soft-state structure.
- *
- * @return	Pointer to soft-state structure.
- */
-static ns8250_t *ns8250_new(void)
-{
-	ns8250_t *ns;
-	
-	ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));
-	if (ns == NULL)
-		return NULL;
-	
-	fibril_mutex_initialize(&ns->mutex);
-	return ns;
-}
-
-/** Delete soft-state structure.
- *
- * @param ns	The driver data structure.
- */
-static void ns8250_delete(ns8250_t *ns)
-{
-	assert(ns != NULL);
-	free(ns);
-}
-
-/** Find out if there is some incomming data available on the serial port.
- *
- * @param port		The base address of the serial port device's ports.
- * @return		True if there are data waiting to be read, false
- *			otherwise.
- */
-static bool ns8250_received(ioport8_t *port)
-{
-	return (pio_read_8(port + 5) & 1) != 0;
-}
-
-/** Read one byte from the serial port.
- *
- * @param port		The base address of the serial port device's ports.
- * @return		The data read.
- */
-static uint8_t ns8250_read_8(ioport8_t *port)
-{
-	return pio_read_8(port);
-}
-
-/** Find out wheter it is possible to send data.
- *
- * @param port		The base address of the serial port device's ports.
- */
-static bool is_transmit_empty(ioport8_t *port)
-{
-	return (pio_read_8(port + 5) & 0x20) != 0;
-}
-
-/** Write one character on the serial port.
- *
- * @param port		The base address of the serial port device's ports.
- * @param c		The character to be written to the serial port device.
- */
-static void ns8250_write_8(ioport8_t *port, uint8_t c)
-{
-	while (!is_transmit_empty(port))
-		;
-	
-	pio_write_8(port, c);
-}
-
-/** Read data from the serial port device.
- *
- * @param fun		The serial port function
- * @param buf		The ouput buffer for read data.
- * @param count		The number of bytes to be read.
- *
- * @return		The number of bytes actually read on success, negative
- *			error number otherwise.
- */
-static int ns8250_read(ddf_fun_t *fun, char *buf, size_t count)
-{
-	ns8250_t *ns = NS8250(fun);
-	int ret = EOK;
-	
-	fibril_mutex_lock(&ns->mutex);
-	while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
-		buf[ret] = (char)buf_pop_front(&ns->input_buffer);
-		ret++;
-	}
-	fibril_mutex_unlock(&ns->mutex);
-	
-	return ret;
-}
-
-/** Write a character to the serial port.
- *
- * @param ns		Serial port device
- * @param c		The character to be written
- */
-static inline void ns8250_putchar(ns8250_t *ns, uint8_t c)
-{
-	fibril_mutex_lock(&ns->mutex);
-	ns8250_write_8(ns->port, c);
-	fibril_mutex_unlock(&ns->mutex);
-}
-
-/** Write data to the serial port.
- *
- * @param fun		The serial port function
- * @param buf		The data to be written
- * @param count		The number of bytes to be written
- * @return		Zero on success
- */
-static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
-{
-	ns8250_t *ns = NS8250(fun);
-	size_t idx;
-	
-	for (idx = 0; idx < count; idx++)
-		ns8250_putchar(ns, (uint8_t) buf[idx]);
-	
-	return 0;
-}
-
-static ddf_dev_ops_t ns8250_dev_ops;
-
-/** The character interface's callbacks. */
-static char_dev_ops_t ns8250_char_dev_ops = {
-	.read = &ns8250_read,
-	.write = &ns8250_write
-};
-
-static int ns8250_add_device(ddf_dev_t *dev);
-
-/** The serial port device driver's standard operations. */
-static driver_ops_t ns8250_ops = {
-	.add_device = &ns8250_add_device
-};
-
-/** The serial port device driver structure. */
-static driver_t ns8250_driver = {
-	.name = NAME,
-	.driver_ops = &ns8250_ops
-};
-
-/** Clean up the serial port soft-state
- *
- * @param ns		Serial port device
- */
-static void ns8250_dev_cleanup(ns8250_t *ns)
-{
-	if (ns->dev->parent_sess) {
-		async_hangup(ns->dev->parent_sess);
-		ns->dev->parent_sess = NULL;
-	}
-}
-
-/** Enable the i/o ports of the device.
- *
- * @param ns		Serial port device
- * @return		True on success, false otherwise
- */
-static bool ns8250_pio_enable(ns8250_t *ns)
-{
-	ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ns->dev->name);
-	
-	/* Gain control over port's registers. */
-	if (pio_enable((void *)(uintptr_t) ns->io_addr, REG_COUNT,
-	    (void **) &ns->port)) {
-		ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
-		    " for device %s.", ns->io_addr, ns->dev->name);
-		return false;
-	}
-	
-	return true;
-}
-
-/** Probe the serial port device for its presence.
- *
- * @param ns		Serial port device
- * @return		True if the device is present, false otherwise
- */
-static bool ns8250_dev_probe(ns8250_t *ns)
-{
-	ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name);
-	
-	ioport8_t *port_addr = ns->port;
-	bool res = true;
-	uint8_t olddata;
-	
-	olddata = pio_read_8(port_addr + 4);
-	
-	pio_write_8(port_addr + 4, 0x10);
-	if (pio_read_8(port_addr + 6) & 0xf0)
-		res = false;
-	
-	pio_write_8(port_addr + 4, 0x1f);
-	if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0)
-		res = false;
-	
-	pio_write_8(port_addr + 4, olddata);
-	
-	if (!res) {
-		ddf_msg(LVL_DEBUG, "Device %s is not present.",
-		    ns->dev->name);
-	}
-	
-	return res;
-}
-
-/** Initialize serial port device.
- *
- * @param ns		Serial port device
- * @return		Zero on success, negative error number otherwise
- */
-static int ns8250_dev_initialize(ns8250_t *ns)
-{
-	ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ns->dev->name);
-	
-	int ret = EOK;
-	
-	hw_resource_list_t hw_resources;
-	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
-	
-	/* Connect to the parent's driver. */
-	ns->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    ns->dev->handle, IPC_FLAG_BLOCKING);
-	if (!ns->dev->parent_sess) {
-		ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
-		    "device %s.", ns->dev->name);
-		ret = ENOENT;
-		goto failed;
-	}
-	
-	/* Get hw resources. */
-	ret = hw_res_get_resource_list(ns->dev->parent_sess, &hw_resources);
-	if (ret != EOK) {
-		ddf_msg(LVL_ERROR, "Failed to get HW resources for device "
-		    "%s.", ns->dev->name);
-		goto failed;
-	}
-	
-	size_t i;
-	hw_resource_t *res;
-	bool irq = false;
-	bool ioport = false;
-	
-	for (i = 0; i < hw_resources.count; i++) {
-		res = &hw_resources.resources[i];
-		switch (res->type) {
-		case INTERRUPT:
-			ns->irq = res->res.interrupt.irq;
-			irq = true;
-			ddf_msg(LVL_NOTE, "Device %s was asigned irq = 0x%x.",
-			    ns->dev->name, ns->irq);
-			break;
-			
-		case IO_RANGE:
-			ns->io_addr = res->res.io_range.address;
-			if (res->res.io_range.size < REG_COUNT) {
-				ddf_msg(LVL_ERROR, "I/O range assigned to "
-				    "device %s is too small.", ns->dev->name);
-				ret = ELIMIT;
-				goto failed;
-			}
-			ioport = true;
-			ddf_msg(LVL_NOTE, "Device %s was asigned I/O address = "
-			    "0x%x.", ns->dev->name, ns->io_addr);
-    			break;
-			
-		default:
-			break;
-		}
-	}
-	
-	if (!irq || !ioport) {
-		ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.",
-		    ns->dev->name);
-		ret = ENOENT;
-		goto failed;
-	}
-	
-	hw_res_clean_resource_list(&hw_resources);
-	return ret;
-	
-failed:
-	ns8250_dev_cleanup(ns);
-	hw_res_clean_resource_list(&hw_resources);
-	return ret;
-}
-
-/** Enable interrupts on the serial port device.
- *
- * Interrupt when data is received
- *
- * @param port		The base address of the serial port device's ports.
- */
-static inline void ns8250_port_interrupts_enable(ioport8_t *port)
-{
-	pio_write_8(port + 1, 0x1);	/* Interrupt when data received. */
-	pio_write_8(port + 4, 0xB);
-}
-
-/** Disable interrupts on the serial port device.
- *
- * @param port		The base address of the serial port device's ports
- */
-static inline void ns8250_port_interrupts_disable(ioport8_t *port)
-{
-	pio_write_8(port + 1, 0x0);	/* Disable all interrupts. */
-}
-
-/** Enable interrupts for the serial port device.
- *
- * @param ns		Serial port device
- * @return		Zero on success, negative error number otherwise
- */
-static int ns8250_interrupt_enable(ns8250_t *ns)
-{
-	/* Enable interrupt on the serial port. */
-	ns8250_port_interrupts_enable(ns->port);
-	
-	return EOK;
-}
-
-/** Set Divisor Latch Access Bit.
- *
- * When the Divisor Latch Access Bit is set, it is possible to set baud rate of
- * the serial port device.
- *
- * @param port		The base address of the serial port device's ports.
- */
-static inline void enable_dlab(ioport8_t *port)
-{
-	uint8_t val = pio_read_8(port + 3);
-	pio_write_8(port + 3, val | DLAB_MASK);
-}
-
-/** Clear Divisor Latch Access Bit.
- *
- * @param port		The base address of the serial port device's ports.
- */
-static inline void clear_dlab(ioport8_t *port)
-{
-	uint8_t val = pio_read_8(port + 3);
-	pio_write_8(port + 3, val & (~DLAB_MASK));
-}
-
-/** Set baud rate of the serial communication on the serial device.
- *
- * @param port		The base address of the serial port device's ports.
- * @param baud_rate	The baud rate to be used by the device.
- * @return		Zero on success, negative error number otherwise (EINVAL
- *			if the specified baud_rate is not valid).
- */
-static int ns8250_port_set_baud_rate(ioport8_t *port, unsigned int baud_rate)
-{
-	uint16_t divisor;
-	uint8_t div_low, div_high;
-	
-	if (baud_rate < 50 || MAX_BAUD_RATE % baud_rate != 0) {
-		ddf_msg(LVL_ERROR, "Invalid baud rate %d requested.",
-		    baud_rate);
-		return EINVAL;
-	}
-	
-	divisor = MAX_BAUD_RATE / baud_rate;
-	div_low = (uint8_t)divisor;
-	div_high = (uint8_t)(divisor >> 8);
-	
-	/* Enable DLAB to be able to access baud rate divisor. */
-	enable_dlab(port);
-	
-	/* Set divisor low byte. */
-	pio_write_8(port + 0, div_low);
-	/* Set divisor high byte. */
-	pio_write_8(port + 1, div_high);
-	
-	clear_dlab(port);
-	
-	return EOK;
-}
-
-/** Get baud rate used by the serial port device.
- *
- * @param port		The base address of the serial port device's ports.
- * @param baud_rate	The ouput parameter to which the baud rate is stored.
- */
-static unsigned int ns8250_port_get_baud_rate(ioport8_t *port)
-{
-	uint16_t divisor;
-	uint8_t div_low, div_high;
-	
-	/* Enable DLAB to be able to access baud rate divisor. */
-	enable_dlab(port);
-	
-	/* Get divisor low byte. */
-	div_low = pio_read_8(port + 0);
-	/* Get divisor high byte. */
-	div_high = pio_read_8(port + 1);
-	
-	clear_dlab(port);
-	
-	divisor = (div_high << 8) | div_low;
-	return MAX_BAUD_RATE / divisor;
-}
-
-/** Get the parameters of the serial communication set on the serial port
- * device.
- *
- * @param parity	The parity used.
- * @param word_length	The length of one data unit in bits.
- * @param stop_bits	The number of stop bits used (one or two).
- */
-static void ns8250_port_get_com_props(ioport8_t *port, unsigned int *parity,
-    unsigned int *word_length, unsigned int *stop_bits)
-{
-	uint8_t val;
-	
-	val = pio_read_8(port + 3);
-	*parity = ((val >> 3) & 7);
-	
-	switch (val & 3) {
-	case WORD_LENGTH_5:
-		*word_length = 5;
-		break;
-	case WORD_LENGTH_6:
-		*word_length = 6;
-		break;
-	case WORD_LENGTH_7:
-		*word_length = 7;
-		break;
-	case WORD_LENGTH_8:
-		*word_length = 8;
-		break;
-	}
-	
-	if ((val >> 2) & 1)
-		*stop_bits = 2;
-	else
-		*stop_bits = 1;
-}
-
-/** Set the parameters of the serial communication on the serial port device.
- *
- * @param parity	The parity to be used.
- * @param word_length	The length of one data unit in bits.
- * @param stop_bits	The number of stop bits used (one or two).
- * @return		Zero on success, EINVAL if some of the specified values
- *			is invalid.
- */
-static int ns8250_port_set_com_props(ioport8_t *port, unsigned int parity,
-    unsigned int word_length, unsigned int stop_bits)
-{
-	uint8_t val;
-	
-	switch (word_length) {
-	case 5:
-		val = WORD_LENGTH_5;
-		break;
-	case 6:
-		val = WORD_LENGTH_6;
-		break;
-	case 7:
-		val = WORD_LENGTH_7;
-		break;
-	case 8:
-		val = WORD_LENGTH_8;
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	switch (stop_bits) {
-	case 1:
-		val |= ONE_STOP_BIT << 2;
-		break;
-	case 2:
-		val |= TWO_STOP_BITS << 2;
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	switch (parity) {
-	case SERIAL_NO_PARITY:
-	case SERIAL_ODD_PARITY:
-	case SERIAL_EVEN_PARITY:
-	case SERIAL_MARK_PARITY:
-	case SERIAL_SPACE_PARITY:
-		val |= parity << 3;
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	pio_write_8(port + 3, val);
-	
-	return EOK;
-}
-
-/** Initialize the serial port device.
- *
- * Set the default parameters of the serial communication.
- *
- * @param ns		Serial port device
- */
-static void ns8250_initialize_port(ns8250_t *ns)
-{
-	ioport8_t *port = ns->port;
-	
-	/* Disable interrupts. */
-	ns8250_port_interrupts_disable(port);
-	/* Set baud rate. */
-	ns8250_port_set_baud_rate(port, 38400);
-	/* 8 bits, no parity, two stop bits. */
-	ns8250_port_set_com_props(port, SERIAL_NO_PARITY, 8, 2);
-	/* Enable FIFO, clear them, with 14-byte threshold. */
-	pio_write_8(port + 2, 0xC7);
-	/*
-	 * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
-	 * Aux Output2 set - needed for interrupts.
-	 */
-	pio_write_8(port + 4, 0x0B);
-}
-
-/** Read the data from the serial port device and store them to the input
- * buffer.
- *
- * @param ns		Serial port device
- */
-static void ns8250_read_from_device(ns8250_t *ns)
-{
-	ioport8_t *port = ns->port;
-	bool cont = true;
-	
-	while (cont) {
-		fibril_mutex_lock(&ns->mutex);
-		
-		cont = ns8250_received(port);
-		if (cont) {
-			uint8_t val = ns8250_read_8(port);
-			
-			if (ns->client_connected) {
-				if (!buf_push_back(&ns->input_buffer, val)) {
-					ddf_msg(LVL_WARN, "Buffer overflow on "
-					    "%s.", ns->dev->name);
-				} else {
-					ddf_msg(LVL_DEBUG2, "Character %c saved "
-					    "to the buffer of %s.",
-					    val, ns->dev->name);
-				}
-			}
-		}
-		
-		fibril_mutex_unlock(&ns->mutex);
-		fibril_yield();
-	}
-}
-
-/** The interrupt handler.
- *
- * The serial port is initialized to interrupt when some data come, so the
- * interrupt is handled by reading the incomming data.
- *
- * @param dev		The serial port device.
- */
-static inline void ns8250_interrupt_handler(ddf_dev_t *dev, ipc_callid_t iid,
-    ipc_call_t *icall)
-{
-	ns8250_read_from_device(NS8250_FROM_DEV(dev));
-}
-
-/** Register the interrupt handler for the device.
- *
- * @param ns		Serial port device
- */
-static inline int ns8250_register_interrupt_handler(ns8250_t *ns)
-{
-	return register_interrupt_handler(ns->dev, ns->irq,
-	    ns8250_interrupt_handler, NULL);
-}
-
-/** Unregister the interrupt handler for the device.
- *
- * @param ns		Serial port device
- */
-static inline int ns8250_unregister_interrupt_handler(ns8250_t *ns)
-{
-	return unregister_interrupt_handler(ns->dev, ns->irq);
-}
-
-/** The add_device callback method of the serial port driver.
- *
- * Probe and initialize the newly added device.
- *
- * @param dev		The serial port device.
- */
-static int ns8250_add_device(ddf_dev_t *dev)
-{
-	ns8250_t *ns = NULL;
-	ddf_fun_t *fun = NULL;
-	bool need_cleanup = false;
-	int rc;
-	
-	ddf_msg(LVL_DEBUG, "ns8250_add_device %s (handle = %d)",
-	    dev->name, (int) dev->handle);
-	
-	/* Allocate soft-state for the device */
-	ns = ns8250_new();
-	if (ns == NULL) {
-		rc = ENOMEM;
-		goto fail;
-	}
-	
-	ns->dev = dev;
-	dev->driver_data = ns;
-	
-	rc = ns8250_dev_initialize(ns);
-	if (rc != EOK)
-		goto fail;
-	
-	need_cleanup = true;
-	
-	if (!ns8250_pio_enable(ns)) {
-		rc = EADDRNOTAVAIL;
-		goto fail;
-	}
-	
-	/* Find out whether the device is present. */
-	if (!ns8250_dev_probe(ns)) {
-		rc = ENOENT;
-		goto fail;
-	}
-	
-	/* Serial port initialization (baud rate etc.). */
-	ns8250_initialize_port(ns);
-	
-	/* Register interrupt handler. */
-	if (ns8250_register_interrupt_handler(ns) != EOK) {
-		ddf_msg(LVL_ERROR, "Failed to register interrupt handler.");
-		rc = EADDRNOTAVAIL;
-		goto fail;
-	}
-	
-	/* Enable interrupt. */
-	rc = ns8250_interrupt_enable(ns);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed to enable the interrupt. Error code = "
-		    "%d.", rc);
-		goto fail;
-	}
-	
-	fun = ddf_fun_create(dev, fun_exposed, "a");
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function.");
-		goto fail;
-	}
-	
-	/* Set device operations. */
-	fun->ops = &ns8250_dev_ops;
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function.");
-		goto fail;
-	}
-
-	ns->fun = fun;
-	
-	ddf_fun_add_to_class(fun, "serial");
-	
-	ddf_msg(LVL_NOTE, "Device %s successfully initialized.",
-	    dev->name);
-	
-	return EOK;
-fail:
-	if (fun != NULL)
-		ddf_fun_destroy(fun);
-	if (need_cleanup)
-		ns8250_dev_cleanup(ns);
-	if (ns != NULL)
-		ns8250_delete(ns);
-	return rc;
-}
-
-/** Open the device.
- *
- * This is a callback function called when a client tries to connect to the
- * device.
- *
- * @param dev		The device.
- */
-static int ns8250_open(ddf_fun_t *fun)
-{
-	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
-	int res;
-	
-	fibril_mutex_lock(&data->mutex);
-	if (data->client_connected) {
-		res = ELIMIT;
-	} else {
-		res = EOK;
-		data->client_connected = true;
-	}
-	fibril_mutex_unlock(&data->mutex);
-	
-	return res;
-}
-
-/** Close the device.
- *
- * This is a callback function called when a client tries to disconnect from
- * the device.
- *
- * @param dev		The device.
- */
-static void ns8250_close(ddf_fun_t *fun)
-{
-	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
-	
-	fibril_mutex_lock(&data->mutex);
-	
-	assert(data->client_connected);
-	
-	data->client_connected = false;
-	buf_clear(&data->input_buffer);
-	
-	fibril_mutex_unlock(&data->mutex);
-}
-
-/** Get parameters of the serial communication which are set to the specified
- * device.
- *
- * @param dev		The serial port device.
- * @param baud_rate	The baud rate used by the device.
- * @param parity	The type of parity used by the device.
- * @param word_length	The size of one data unit in bits.
- * @param stop_bits	The number of stop bits used.
- */
-static void
-ns8250_get_props(ddf_dev_t *dev, unsigned int *baud_rate, unsigned int *parity,
-    unsigned int *word_length, unsigned int* stop_bits)
-{
-	ns8250_t *data = (ns8250_t *) dev->driver_data;
-	ioport8_t *port = data->port;
-	
-	fibril_mutex_lock(&data->mutex);
-	ns8250_port_interrupts_disable(port);
-	*baud_rate = ns8250_port_get_baud_rate(port);
-	ns8250_port_get_com_props(port, parity, word_length, stop_bits);
-	ns8250_port_interrupts_enable(port);
-	fibril_mutex_unlock(&data->mutex);
-	
-	ddf_msg(LVL_DEBUG, "ns8250_get_props: baud rate %d, parity 0x%x, word "
-	    "length %d, stop bits %d", *baud_rate, *parity, *word_length,
-	    *stop_bits);
-}
-
-/** Set parameters of the serial communication to the specified serial port
- * device.
- *
- * @param dev		The serial port device.
- * @param baud_rate	The baud rate to be used by the device.
- * @param parity	The type of parity to be used by the device.
- * @param word_length	The size of one data unit in bits.
- * @param stop_bits	The number of stop bits to be used.
- */
-static int ns8250_set_props(ddf_dev_t *dev, unsigned int baud_rate,
-    unsigned int parity, unsigned int word_length, unsigned int stop_bits)
-{
-	ddf_msg(LVL_DEBUG, "ns8250_set_props: baud rate %d, parity 0x%x, word "
-	    "length %d, stop bits %d", baud_rate, parity, word_length,
-	    stop_bits);
-	
-	ns8250_t *data = (ns8250_t *) dev->driver_data;
-	ioport8_t *port = data->port;
-	int ret;
-	
-	fibril_mutex_lock(&data->mutex);
-	ns8250_port_interrupts_disable(port);
-	ret = ns8250_port_set_baud_rate(port, baud_rate);
-	if (ret == EOK)
-		ret = ns8250_port_set_com_props(port, parity, word_length, stop_bits);
-	ns8250_port_interrupts_enable(port);
-	fibril_mutex_unlock(&data->mutex);
-	
-	return ret;
-}
-
-/** Default handler for client requests which are not handled by the standard
- * interfaces.
- *
- * Configure the parameters of the serial communication.
- */
-static void ns8250_default_handler(ddf_fun_t *fun, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	sysarg_t method = IPC_GET_IMETHOD(*call);
-	int ret;
-	unsigned int baud_rate, parity, word_length, stop_bits;
-	
-	switch (method) {
-	case SERIAL_GET_COM_PROPS:
-		ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
-		    &stop_bits);
-		async_answer_4(callid, EOK, baud_rate, parity, word_length,
-		    stop_bits);
-		break;
-		
-	case SERIAL_SET_COM_PROPS:
- 		baud_rate = IPC_GET_ARG1(*call);
-		parity = IPC_GET_ARG2(*call);
-		word_length = IPC_GET_ARG3(*call);
-		stop_bits = IPC_GET_ARG4(*call);
-		ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
-		    stop_bits);
-		async_answer_0(callid, ret);
-		break;
-		
-	default:
-		async_answer_0(callid, ENOTSUP);
-	}
-}
-
-/** Initialize the serial port driver.
- *
- * Initialize device operations structures with callback methods for handling
- * client requests to the serial port devices.
- */
-static void ns8250_init(void)
-{
-	ddf_log_init(NAME, LVL_ERROR);
-	
-	ns8250_dev_ops.open = &ns8250_open;
-	ns8250_dev_ops.close = &ns8250_close;
-	
-	ns8250_dev_ops.interfaces[CHAR_DEV_IFACE] = &ns8250_char_dev_ops;
-	ns8250_dev_ops.default_handler = &ns8250_default_handler;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS serial port driver\n");
-	ns8250_init();
-	return ddf_driver_main(&ns8250_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/ns8250/ns8250.ma
===================================================================
--- uspace/drv/ns8250/ns8250.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 isa/ns8250
Index: pace/drv/ohci/Makefile
===================================================================
--- uspace/drv/ohci/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,58 +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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBHOST_PREFIX)/libusbhost.a \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBUSBHOST_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = ohci
-
-SOURCES = \
-	batch.c \
-	endpoint_list.c \
-	hc.c \
-	hcd_endpoint.c \
-	iface.c \
-	main.c \
-	ohci.c \
-	pci.c \
-	root_hub.c \
-	hw_struct/endpoint_descriptor.c \
-	hw_struct/transfer_descriptor.c
-
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/ohci/batch.c
===================================================================
--- uspace/drv/ohci/batch.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,429 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver USB transaction structure
- */
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/usb.h>
-#include <usb/debug.h>
-
-#include "batch.h"
-#include "hcd_endpoint.h"
-#include "utils/malloc32.h"
-#include "hw_struct/endpoint_descriptor.h"
-#include "hw_struct/transfer_descriptor.h"
-
-/** OHCI specific data required for USB transfer */
-typedef struct ohci_transfer_batch {
-	/** Endpoint descriptor of the target endpoint. */
-	ed_t *ed;
-	/** List of TDs needed for the transfer */
-	td_t **tds;
-	/** Number of TDs used by the transfer */
-	size_t td_count;
-	/** Dummy TD to be left at the ED and used by the next transfer */
-	size_t leave_td;
-	/** Data buffer, must be accessible byb the OHCI hw. */
-	void *device_buffer;
-} ohci_transfer_batch_t;
-/*----------------------------------------------------------------------------*/
-static void batch_control(usb_transfer_batch_t *instance,
-    usb_direction_t data_dir, usb_direction_t status_dir);
-static void batch_data(usb_transfer_batch_t *instance);
-/*----------------------------------------------------------------------------*/
-/** Safely destructs ohci_transfer_batch_t structure
- *
- * @param[in] ohci_batch Instance to destroy.
- */
-static void ohci_transfer_batch_dispose(void *ohci_batch)
-{
-	ohci_transfer_batch_t *instance = ohci_batch;
-	if (!instance)
-		return;
-	free32(instance->device_buffer);
-	unsigned i = 0;
-	if (instance->tds) {
-		for (; i< instance->td_count; ++i) {
-			if (i != instance->leave_td)
-				free32(instance->tds[i]);
-		}
-		free(instance->tds);
-	}
-	free(instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Allocate memory initialize internal structures
- *
- * @param[in] fun DDF function to pass to callback.
- * @param[in] ep Communication target
- * @param[in] buffer Data source/destination.
- * @param[in] buffer_size Size of the buffer.
- * @param[in] setup_buffer Setup data source (if not NULL)
- * @param[in] setup_size Size of setup_buffer (should be always 8)
- * @param[in] func_in function to call on inbound transfer completion
- * @param[in] func_out function to call on outbound transfer completion
- * @param[in] arg additional parameter to func_in or func_out
- * @return Valid pointer if all structures were successfully created,
- * NULL otherwise.
- *
- * Allocates and initializes structures needed by the OHCI hw for the transfer.
- */
-usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
-    char *buffer, size_t buffer_size,
-    const 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)
-{
-#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
-        if (ptr == NULL) { \
-                usb_log_error(message); \
-                if (instance) { \
-                        usb_transfer_batch_dispose(instance); \
-                } \
-                return NULL; \
-        } else (void)0
-
-	usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
-	CHECK_NULL_DISPOSE_RETURN(instance,
-	    "Failed to allocate batch instance.\n");
-	usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size,
-	    NULL, setup_size, func_in, func_out, arg, fun, NULL,
-	    ohci_transfer_batch_dispose);
-
-	const hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
-	assert(hcd_ep);
-
-	ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1);
-	CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
-	instance->private_data = data;
-
-	data->td_count =
-	    ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
-	/* Control transfer need Setup and Status stage */
-	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
-		data->td_count += 2;
-	}
-
-	/* We need an extra place for TD that is currently assigned to hcd_ep*/
-	data->tds = calloc(sizeof(td_t*), data->td_count + 1);
-	CHECK_NULL_DISPOSE_RETURN(data->tds,
-	    "Failed to allocate transfer descriptors.\n");
-
-	/* Add TD left over by the previous transfer */
-	data->tds[0] = hcd_ep->td;
-	data->leave_td = 0;
-	unsigned i = 1;
-	for (; i <= data->td_count; ++i) {
-		data->tds[i] = malloc32(sizeof(td_t));
-		CHECK_NULL_DISPOSE_RETURN(data->tds[i],
-		    "Failed to allocate TD %d.\n", i );
-	}
-
-	data->ed = hcd_ep->ed;
-
-	/* NOTE: OHCI is capable of handling buffer that crosses page boundaries
-	 * it is, however, not capable of handling buffer that occupies more
-	 * than two pages (the first page is computed using start pointer, the
-	 * other using the end pointer) */
-        if (setup_size + buffer_size > 0) {
-		data->device_buffer = malloc32(setup_size + buffer_size);
-                CHECK_NULL_DISPOSE_RETURN(data->device_buffer,
-                    "Failed to allocate device accessible buffer.\n");
-		instance->setup_buffer = data->device_buffer;
-		instance->data_buffer = data->device_buffer + setup_size;
-                memcpy(instance->setup_buffer, setup_buffer, setup_size);
-        }
-
-	return instance;
-}
-/*----------------------------------------------------------------------------*/
-/** Check batch TDs' status.
- *
- * @param[in] instance Batch structure to use.
- * @return False, if there is an active TD, true otherwise.
- *
- * Walk all TDs (usually there is just one). Stop with false if there is an
- * active TD. Stop with true if an error is found. Return true if the walk
- * completes with the last TD.
- */
-bool batch_is_complete(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	ohci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-	usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n",
-	    instance, data->td_count);
-	usb_log_debug("ED: %x:%x:%x:%x.\n",
-	    data->ed->status, data->ed->td_head, data->ed->td_tail,
-	    data->ed->next);
-	size_t i = 0;
-	instance->transfered_size = instance->buffer_size;
-	for (; i < data->td_count; ++i) {
-		assert(data->tds[i] != NULL);
-		usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
-		    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
-		    data->tds[i]->be);
-		if (!td_is_finished(data->tds[i])) {
-			return false;
-		}
-		instance->error = td_error(data->tds[i]);
-		if (instance->error != EOK) {
-			usb_log_debug("Batch(%p) found error TD(%zu):%x.\n",
-			    instance, i, data->tds[i]->status);
-			/* Make sure TD queue is empty (one TD),
-			 * ED should be marked as halted */
-			data->ed->td_tail =
-			    (data->ed->td_head & ED_TDTAIL_PTR_MASK);
-			++i;
-			break;
-		}
-	}
-	data->leave_td = i;
-	assert(data->leave_td <= data->td_count);
-	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
-	assert(hcd_ep);
-	hcd_ep->td = data->tds[i];
-	assert(i > 0);
-	for (--i;i < data->td_count; ++i)
-		instance->transfered_size -= td_remain_size(data->tds[i]);
-
-	/* Clear possible ED HALT */
-	data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
-	const uint32_t pa = addr_to_phys(hcd_ep->td);
-	assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
-	assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
-
-	return true;
-}
-/*----------------------------------------------------------------------------*/
-/** Starts execution of the TD list
- *
- * @param[in] instance Batch structure to use
- */
-void batch_commit(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	ohci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-	ed_set_end_td(data->ed, data->tds[data->td_count]);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepares control write transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Uses generic control transfer using direction OUT(data stage) and
- * IN(status stage).
- */
-void batch_control_write(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	/* We are data out, we are supposed to provide data */
-	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
-	instance->next_step = usb_transfer_batch_call_out_and_dispose;
-	batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
-	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepares control read transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Uses generic control transfer using direction IN(data stage) and
- * OUT(status stage).
- */
-void batch_control_read(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	instance->next_step = usb_transfer_batch_call_in_and_dispose;
-	batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
-	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare interrupt in transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transfer.
- */
-void batch_interrupt_in(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	instance->next_step = usb_transfer_batch_call_in_and_dispose;
-	batch_data(instance);
-	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare interrupt out transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transfer.
- */
-void batch_interrupt_out(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	/* We are data out, we are supposed to provide data */
-	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
-	instance->next_step = usb_transfer_batch_call_out_and_dispose;
-	batch_data(instance);
-	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare bulk in transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transfer.
- */
-void batch_bulk_in(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	instance->next_step = usb_transfer_batch_call_in_and_dispose;
-	batch_data(instance);
-	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare bulk out transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transfer.
- */
-void batch_bulk_out(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	/* We are data out, we are supposed to provide data */
-	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
-	instance->next_step = usb_transfer_batch_call_out_and_dispose;
-	batch_data(instance);
-	usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare generic control transfer
- *
- * @param[in] instance Batch structure to use.
- * @param[in] data_dir Direction to use for data stage.
- * @param[in] status_dir Direction to use for status stage.
- *
- * Setup stage with toggle 0 and direction BOTH(SETUP_PID)
- * Data stage with alternating toggle and direction supplied by parameter.
- * Status stage with toggle 1 and direction supplied by parameter.
- */
-void batch_control(usb_transfer_batch_t *instance,
-    usb_direction_t data_dir, usb_direction_t status_dir)
-{
-	assert(instance);
-	ohci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-	usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
-	    data->ed->status, data->ed->td_tail, data->ed->td_head,
-	    data->ed->next);
-	int toggle = 0;
-	/* setup stage */
-	td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
-		instance->setup_size, toggle);
-	td_set_next(data->tds[0], data->tds[1]);
-	usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
-	    data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
-
-	/* data stage */
-	size_t td_current = 1;
-	size_t remain_size = instance->buffer_size;
-	char *buffer = instance->data_buffer;
-	while (remain_size > 0) {
-		size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
-		    OHCI_TD_MAX_TRANSFER : remain_size;
-		toggle = 1 - toggle;
-
-		td_init(data->tds[td_current], data_dir, buffer,
-		    transfer_size, toggle);
-		td_set_next(data->tds[td_current], data->tds[td_current + 1]);
-		usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
-		    data->tds[td_current]->status, data->tds[td_current]->cbp,
-		    data->tds[td_current]->next, data->tds[td_current]->be);
-
-		buffer += transfer_size;
-		remain_size -= transfer_size;
-		assert(td_current < data->td_count - 1);
-		++td_current;
-	}
-
-	/* status stage */
-	assert(td_current == data->td_count - 1);
-	td_init(data->tds[td_current], status_dir, NULL, 0, 1);
-	td_set_next(data->tds[td_current], data->tds[td_current + 1]);
-	usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
-	    data->tds[td_current]->status, data->tds[td_current]->cbp,
-	    data->tds[td_current]->next, data->tds[td_current]->be);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare generic data transfer
- *
- * @param[in] instance Batch structure to use.
- *
- * Direction is supplied by the associated ep and toggle is maintained by the
- * OHCI hw in ED.
- */
-void batch_data(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	ohci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-	usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
-	    data->ed->status, data->ed->td_tail, data->ed->td_head,
-	    data->ed->next);
-
-	size_t td_current = 0;
-	size_t remain_size = instance->buffer_size;
-	char *buffer = instance->data_buffer;
-	while (remain_size > 0) {
-		const size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER
-		    ? OHCI_TD_MAX_TRANSFER : remain_size;
-
-		td_init(data->tds[td_current], instance->ep->direction,
-		    buffer, transfer_size, -1);
-		td_set_next(data->tds[td_current], data->tds[td_current + 1]);
-		usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
-		    data->tds[td_current]->status, data->tds[td_current]->cbp,
-		    data->tds[td_current]->next, data->tds[td_current]->be);
-
-		buffer += transfer_size;
-		remain_size -= transfer_size;
-		assert(td_current < data->td_count);
-		++td_current;
-	}
-}
-/**
- * @}
- */
Index: pace/drv/ohci/batch.h
===================================================================
--- uspace/drv/ohci/batch.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,68 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver USB transaction structure
- */
-#ifndef DRV_OHCI_BATCH_H
-#define DRV_OHCI_BATCH_H
-
-#include <usbhc_iface.h>
-#include <usb/usb.h>
-#include <usb/host/device_keeper.h>
-#include <usb/host/endpoint.h>
-#include <usb/host/batch.h>
-
-usb_transfer_batch_t * batch_get(
-    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
-    const 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(usb_transfer_batch_t *instance);
-
-void batch_commit(usb_transfer_batch_t *instance);
-
-void batch_control_write(usb_transfer_batch_t *instance);
-
-void batch_control_read(usb_transfer_batch_t *instance);
-
-void batch_interrupt_in(usb_transfer_batch_t *instance);
-
-void batch_interrupt_out(usb_transfer_batch_t *instance);
-
-void batch_bulk_in(usb_transfer_batch_t *instance);
-
-void batch_bulk_out(usb_transfer_batch_t *instance);
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/endpoint_list.c
===================================================================
--- uspace/drv/ohci/endpoint_list.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,179 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver transfer list implementation
- */
-#include <errno.h>
-#include <usb/debug.h>
-#include <arch/barrier.h>
-
-#include "endpoint_list.h"
-
-/** Initialize transfer list structures.
- *
- * @param[in] instance Memory place to use.
- * @param[in] name Name of the new list.
- * @return Error code
- *
- * Allocates memory for internal ed_t structure.
- */
-int endpoint_list_init(endpoint_list_t *instance, const char *name)
-{
-	assert(instance);
-	instance->name = name;
-	instance->list_head = malloc32(sizeof(ed_t));
-	if (!instance->list_head) {
-		usb_log_error("Failed to allocate list head.\n");
-		return ENOMEM;
-	}
-	instance->list_head_pa = addr_to_phys(instance->list_head);
-	usb_log_debug2("Transfer list %s setup with ED: %p(0x%0" PRIx32 ")).\n",
-	    name, instance->list_head, instance->list_head_pa);
-
-	ed_init(instance->list_head, NULL);
-	list_initialize(&instance->endpoint_list);
-	fibril_mutex_initialize(&instance->guard);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Set the next list in transfer list chain.
- *
- * @param[in] instance List to lead.
- * @param[in] next List to append.
- *
- * Does not check whether this replaces an existing list.
- */
-void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
-{
-	assert(instance);
-	assert(next);
-	ed_append_ed(instance->list_head, next->list_head);
-}
-/*----------------------------------------------------------------------------*/
-/** Add endpoint to the list and queue.
- *
- * @param[in] instance List to use.
- * @param[in] endpoint Endpoint to add.
- *
- * The endpoint is added to the end of the list and queue.
- */
-void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
-{
-	assert(instance);
-	assert(hcd_ep);
-	usb_log_debug2("Queue %s: Adding endpoint(%p).\n",
-	    instance->name, hcd_ep);
-
-	fibril_mutex_lock(&instance->guard);
-
-	ed_t *last_ed = NULL;
-	/* Add to the hardware queue. */
-	if (list_empty(&instance->endpoint_list)) {
-		/* There are no active EDs */
-		last_ed = instance->list_head;
-	} else {
-		/* There are active EDs, get the last one */
-		hcd_endpoint_t *last = list_get_instance(
-		    instance->endpoint_list.prev, hcd_endpoint_t, link);
-		assert(last);
-		last_ed = last->ed;
-	}
-	/* Keep link */
-	hcd_ep->ed->next = last_ed->next;
-	/* Make sure ED is written to the memory */
-	write_barrier();
-
-	/* Add ed to the hw queue */
-	ed_append_ed(last_ed, hcd_ep->ed);
-	/* Make sure ED is updated */
-	write_barrier();
-
-	/* Add to the sw list */
-	list_append(&hcd_ep->link, &instance->endpoint_list);
-
-	hcd_endpoint_t *first = list_get_instance(
-	    instance->endpoint_list.next, hcd_endpoint_t, link);
-	usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n",
-		hcd_ep, instance->name, first, first->ed);
-	if (last_ed == instance->list_head) {
-		usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n",
-		    instance->name, last_ed, instance->list_head_pa,
-		    last_ed->status, last_ed->td_tail, last_ed->td_head,
-		    last_ed->next);
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Remove endpoint from the list and queue.
- *
- * @param[in] instance List to use.
- * @param[in] endpoint Endpoint to remove.
- */
-void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
-{
-	assert(instance);
-	assert(instance->list_head);
-	assert(hcd_ep);
-	assert(hcd_ep->ed);
-
-	fibril_mutex_lock(&instance->guard);
-
-	usb_log_debug2(
-	    "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
-
-	const char *qpos = NULL;
-	ed_t *prev_ed;
-	/* Remove from the hardware queue */
-	if (instance->endpoint_list.next == &hcd_ep->link) {
-		/* I'm the first one here */
-		prev_ed = instance->list_head;
-		qpos = "FIRST";
-	} else {
-		hcd_endpoint_t *prev =
-		    list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link);
-		prev_ed = prev->ed;
-		qpos = "NOT FIRST";
-	}
-	assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
-	prev_ed->next = hcd_ep->ed->next;
-	/* Make sure ED is updated */
-	write_barrier();
-
-	usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
-	    hcd_ep, qpos, instance->name, hcd_ep->ed->next);
-
-	/* Remove from the endpoint list */
-	list_remove(&hcd_ep->link);
-	fibril_mutex_unlock(&instance->guard);
-}
-/**
- * @}
- */
Index: pace/drv/ohci/endpoint_list.h
===================================================================
--- uspace/drv/ohci/endpoint_list.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,76 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver transfer list structure
- */
-#ifndef DRV_OHCI_ENDPOINT_LIST_H
-#define DRV_OHCI_ENDPOINT_LIST_H
-
-#include <fibril_synch.h>
-
-#include "hcd_endpoint.h"
-#include "hw_struct/endpoint_descriptor.h"
-#include "utils/malloc32.h"
-
-/** Structure maintains both OHCI queue and software list of active endpoints.*/
-typedef struct endpoint_list {
-	/** Guard against add/remove races */
-	fibril_mutex_t guard;
-	/** OHCI hw structure at the beginning of the queue */
-	ed_t *list_head;
-	/** Physical address of the first(dummy) ED */
-	uint32_t list_head_pa;
-	/** Assigned name, provides nicer debug output */
-	const char *name;
-	/** Sw list of all active EDs */
-	link_t endpoint_list;
-} endpoint_list_t;
-
-/** Dispose transfer list structures.
- *
- * @param[in] instance Memory place to use.
- *
- * Frees memory of the internal ed_t structure.
- */
-static inline void endpoint_list_fini(endpoint_list_t *instance)
-{
-	assert(instance);
-	free32(instance->list_head);
-}
-
-int endpoint_list_init(endpoint_list_t *instance, const char *name);
-void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
-void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
-void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,624 +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 drvusbohcihc
- * @{
- */
-/** @file
- * @brief OHCI Host controller driver routines
- */
-#include <errno.h>
-#include <str_error.h>
-#include <adt/list.h>
-#include <libarch/ddi.h>
-
-#include <usb/debug.h>
-#include <usb/usb.h>
-#include <usb/ddfiface.h>
-
-#include "hc.h"
-#include "hcd_endpoint.h"
-
-#define OHCI_USED_INTERRUPTS \
-    (I_SO | I_WDH | I_UE | I_RHSC)
-static int interrupt_emulator(hc_t *instance);
-static void hc_gain_control(hc_t *instance);
-static int hc_init_transfer_lists(hc_t *instance);
-static int hc_init_memory(hc_t *instance);
-/*----------------------------------------------------------------------------*/
-/** Announce OHCI root hub to the DDF
- *
- * @param[in] instance OHCI driver intance
- * @param[in] hub_fun DDF fuction representing OHCI root hub
- * @return Error code
- */
-int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
-{
-	assert(instance);
-	assert(hub_fun);
-
-	const usb_address_t hub_address =
-	    device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
-	if (hub_address <= 0) {
-		usb_log_error("Failed(%d) to get OHCI root hub address.\n",
-		    hub_address);
-		return hub_address;
-	}
-	instance->rh.address = hub_address;
-	usb_device_keeper_bind(
-	    &instance->manager, hub_address, hub_fun->handle);
-
-#define CHECK_RET_RELEASE(ret, message...) \
-if (ret != EOK) { \
-	usb_log_error(message); \
-	hc_remove_endpoint(instance, hub_address, 0, USB_DIRECTION_BOTH); \
-	usb_device_keeper_release(&instance->manager, hub_address); \
-	return ret; \
-} else (void)0
-
-	int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
-	    USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
-	CHECK_RET_RELEASE(ret, "Failed(%d) to add OHCI rh endpoint 0.\n", ret);
-
-	char *match_str = NULL;
-	/* DDF needs heap allocated string */
-	ret = asprintf(&match_str, "usb&class=hub");
-	ret = ret > 0 ? 0 : ret;
-	CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret);
-
-	ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
-	CHECK_RET_RELEASE(ret, "Failed(%d) add root hub match-id.\n", ret);
-
-	ret = ddf_fun_bind(hub_fun);
-	CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret);
-
-	return EOK;
-#undef CHECK_RET_RELEASE
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize OHCI hc driver structure
- *
- * @param[in] instance Memory place for the structure.
- * @param[in] regs Address of the memory mapped I/O registers.
- * @param[in] reg_size Size of the memory mapped area.
- * @param[in] interrupts True if w interrupts should be used
- * @return Error code
- */
-int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
-{
-	assert(instance);
-	int ret = EOK;
-#define CHECK_RET_RETURN(ret, message...) \
-if (ret != EOK) { \
-	usb_log_error(message); \
-	return ret; \
-} else (void)0
-
-	ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to gain access to device registers: %s.\n",
-	    ret, str_error(ret));
-
-	list_initialize(&instance->pending_batches);
-	usb_device_keeper_init(&instance->manager);
-	ret = usb_endpoint_manager_init(&instance->ep_manager,
-	    BANDWIDTH_AVAILABLE_USB11);
-	CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
-	    str_error(ret));
-
-	ret = hc_init_memory(instance);
-	CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",
-	    str_error(ret));
-#undef CHECK_RET_RETURN
-
-	fibril_mutex_initialize(&instance->guard);
-	hc_gain_control(instance);
-
-	rh_init(&instance->rh, instance->registers);
-
-	if (!interrupts) {
-		instance->interrupt_emulator =
-		    fibril_create((int(*)(void*))interrupt_emulator, instance);
-		fibril_add_ready(instance->interrupt_emulator);
-	}
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Create end register endpoint structures
- *
- * @param[in] instance OHCI driver structure.
- * @param[in] address USB address of the device.
- * @param[in] endpoint USB endpoint number.
- * @param[in] speed Communication speeed of the device.
- * @param[in] type Endpoint's transfer type.
- * @param[in] direction Endpoint's direction.
- * @param[in] mps Maximum packet size the endpoint accepts.
- * @param[in] size Maximum allowed buffer size.
- * @param[in] interval Time between transfers(interrupt transfers only).
- * @return Error code
- */
-int hc_add_endpoint(
-    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
-    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
-    size_t mps, size_t size, unsigned interval)
-{
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
-	if (ep == NULL)
-		return ENOMEM;
-	int ret =
-	    endpoint_init(ep, address, endpoint, direction, type, speed, mps);
-	if (ret != EOK) {
-		free(ep);
-		return ret;
-	}
-
-	hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
-	if (hcd_ep == NULL) {
-		endpoint_destroy(ep);
-		return ENOMEM;
-	}
-
-	ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
-	if (ret != EOK) {
-		hcd_endpoint_clear(ep);
-		endpoint_destroy(ep);
-		return ret;
-	}
-
-	/* Enqueue hcd_ep */
-	switch (ep->transfer_type) {
-	case USB_TRANSFER_CONTROL:
-		instance->registers->control &= ~C_CLE;
-		endpoint_list_add_ep(
-		    &instance->lists[ep->transfer_type], hcd_ep);
-		instance->registers->control_current = 0;
-		instance->registers->control |= C_CLE;
-		break;
-	case USB_TRANSFER_BULK:
-		instance->registers->control &= ~C_BLE;
-		endpoint_list_add_ep(
-		    &instance->lists[ep->transfer_type], hcd_ep);
-		instance->registers->control |= C_BLE;
-		break;
-	case USB_TRANSFER_ISOCHRONOUS:
-	case USB_TRANSFER_INTERRUPT:
-		instance->registers->control &= (~C_PLE & ~C_IE);
-		endpoint_list_add_ep(
-		    &instance->lists[ep->transfer_type], hcd_ep);
-		instance->registers->control |= C_PLE | C_IE;
-		break;
-	default:
-		break;
-	}
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Dequeue and delete endpoint structures
- *
- * @param[in] instance OHCI hc driver structure.
- * @param[in] address USB address of the device.
- * @param[in] endpoint USB endpoint number.
- * @param[in] direction Direction of the endpoint.
- * @return Error code
- */
-int hc_remove_endpoint(hc_t *instance, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
-	    address, endpoint, direction, NULL);
-	if (ep == NULL) {
-		usb_log_error("Endpoint unregister failed: No such EP.\n");
-		fibril_mutex_unlock(&instance->guard);
-		return ENOENT;
-	}
-
-	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
-	if (hcd_ep) {
-		/* Dequeue hcd_ep */
-		switch (ep->transfer_type) {
-		case USB_TRANSFER_CONTROL:
-			instance->registers->control &= ~C_CLE;
-			endpoint_list_remove_ep(
-			    &instance->lists[ep->transfer_type], hcd_ep);
-			instance->registers->control_current = 0;
-			instance->registers->control |= C_CLE;
-			break;
-		case USB_TRANSFER_BULK:
-			instance->registers->control &= ~C_BLE;
-			endpoint_list_remove_ep(
-			    &instance->lists[ep->transfer_type], hcd_ep);
-			instance->registers->control |= C_BLE;
-			break;
-		case USB_TRANSFER_ISOCHRONOUS:
-		case USB_TRANSFER_INTERRUPT:
-			instance->registers->control &= (~C_PLE & ~C_IE);
-			endpoint_list_remove_ep(
-			    &instance->lists[ep->transfer_type], hcd_ep);
-			instance->registers->control |= C_PLE | C_IE;
-			break;
-		default:
-			break;
-		}
-		hcd_endpoint_clear(ep);
-	} else {
-		usb_log_warning("Endpoint without hcd equivalent structure.\n");
-	}
-	int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
-	    address, endpoint, direction);
-	fibril_mutex_unlock(&instance->guard);
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Get access to endpoint structures
- *
- * @param[in] instance OHCI hc driver structure.
- * @param[in] address USB address of the device.
- * @param[in] endpoint USB endpoint number.
- * @param[in] direction Direction of the endpoint.
- * @param[out] bw Reserved bandwidth.
- * @return Error code
- */
-endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
-	    address, endpoint, direction, bw);
-	fibril_mutex_unlock(&instance->guard);
-	return ep;
-}
-/*----------------------------------------------------------------------------*/
-/** Add USB transfer to the schedule.
- *
- * @param[in] instance OHCI hc driver structure.
- * @param[in] batch Batch representing the transfer.
- * @return Error code.
- */
-int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
-{
-	assert(instance);
-	assert(batch);
-	assert(batch->ep);
-
-	/* Check for root hub communication */
-	if (batch->ep->address == instance->rh.address) {
-		return rh_request(&instance->rh, batch);
-	}
-
-	fibril_mutex_lock(&instance->guard);
-	list_append(&batch->link, &instance->pending_batches);
-	batch_commit(batch);
-
-	/* Control and bulk schedules need a kick to start working */
-	switch (batch->ep->transfer_type)
-	{
-	case USB_TRANSFER_CONTROL:
-		instance->registers->command_status |= CS_CLF;
-		break;
-	case USB_TRANSFER_BULK:
-		instance->registers->command_status |= CS_BLF;
-		break;
-	default:
-		break;
-	}
-	fibril_mutex_unlock(&instance->guard);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Interrupt handling routine
- *
- * @param[in] instance OHCI hc driver structure.
- * @param[in] status Value of the status register at the time of interrupt.
- */
-void hc_interrupt(hc_t *instance, uint32_t status)
-{
-	assert(instance);
-	if ((status & ~I_SF) == 0) /* ignore sof status */
-		return;
-	usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
-	if (status & I_RHSC)
-		rh_interrupt(&instance->rh);
-
-	if (status & I_WDH) {
-		fibril_mutex_lock(&instance->guard);
-		usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
-		    instance->registers->hcca,
-		    (void *) addr_to_phys(instance->hcca));
-		usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
-		    instance->registers->periodic_current);
-
-		link_t *current = instance->pending_batches.next;
-		while (current != &instance->pending_batches) {
-			link_t *next = current->next;
-			usb_transfer_batch_t *batch =
-			    usb_transfer_batch_from_link(current);
-
-			if (batch_is_complete(batch)) {
-				list_remove(current);
-				usb_transfer_batch_finish(batch);
-			}
-			current = next;
-		}
-		fibril_mutex_unlock(&instance->guard);
-	}
-
-	if (status & I_UE) {
-		hc_start_hw(instance);
-	}
-
-}
-/*----------------------------------------------------------------------------*/
-/** Check status register regularly
- *
- * @param[in] instance OHCI hc driver structure.
- * @return Error code
- */
-int interrupt_emulator(hc_t *instance)
-{
-	assert(instance);
-	usb_log_info("Started interrupt emulator.\n");
-	while (1) {
-		const uint32_t status = instance->registers->interrupt_status;
-		instance->registers->interrupt_status = status;
-		hc_interrupt(instance, status);
-		async_usleep(10000);
-	}
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Turn off any (BIOS)driver that might be in control of the device.
- *
- * @param[in] instance OHCI hc driver structure.
- */
-void hc_gain_control(hc_t *instance)
-{
-	assert(instance);
-	usb_log_debug("Requesting OHCI control.\n");
-	/* Turn off legacy emulation */
-	volatile uint32_t *ohci_emulation_reg =
-	    (uint32_t*)((char*)instance->registers + 0x100);
-	usb_log_debug("OHCI legacy register %p: %x.\n",
-	    ohci_emulation_reg, *ohci_emulation_reg);
-	/* Do not change A20 state */
-	*ohci_emulation_reg &= 0x100;
-	usb_log_debug("OHCI legacy register %p: %x.\n",
-	    ohci_emulation_reg, *ohci_emulation_reg);
-
-	/* Interrupt routing enabled => smm driver is active */
-	if (instance->registers->control & C_IR) {
-		usb_log_debug("SMM driver: request ownership change.\n");
-		instance->registers->command_status |= CS_OCR;
-		while (instance->registers->control & C_IR) {
-			async_usleep(1000);
-		}
-		usb_log_info("SMM driver: Ownership taken.\n");
-		instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);
-		async_usleep(50000);
-		return;
-	}
-
-	const unsigned hc_status =
-	    (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK;
-	/* Interrupt routing disabled && status != USB_RESET => BIOS active */
-	if (hc_status != C_HCFS_RESET) {
-		usb_log_debug("BIOS driver found.\n");
-		if (hc_status == C_HCFS_OPERATIONAL) {
-			usb_log_info("BIOS driver: HC operational.\n");
-			return;
-		}
-		/* HC is suspended assert resume for 20ms */
-		instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
-		async_usleep(20000);
-		usb_log_info("BIOS driver: HC resumed.\n");
-		return;
-	}
-
-	/* HC is in reset (hw startup) => no other driver
-	 * maintain reset for at least the time specified in USB spec (50 ms)*/
-	usb_log_info("HC found in reset.\n");
-	async_usleep(50000);
-}
-/*----------------------------------------------------------------------------*/
-/** OHCI hw initialization routine.
- *
- * @param[in] instance OHCI hc driver structure.
- */
-void hc_start_hw(hc_t *instance)
-{
-	/* OHCI guide page 42 */
-	assert(instance);
-	usb_log_debug2("Started hc initialization routine.\n");
-
-	/* Save contents of fm_interval register */
-	const uint32_t fm_interval = instance->registers->fm_interval;
-	usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
-
-	/* Reset hc */
-	usb_log_debug2("HC reset.\n");
-	size_t time = 0;
-	instance->registers->command_status = CS_HCR;
-	while (instance->registers->command_status & CS_HCR) {
-		async_usleep(10);
-		time += 10;
-	}
-	usb_log_debug2("HC reset complete in %zu us.\n", time);
-
-	/* Restore fm_interval */
-	instance->registers->fm_interval = fm_interval;
-	assert((instance->registers->command_status & CS_HCR) == 0);
-
-	/* hc is now in suspend state */
-	usb_log_debug2("HC should be in suspend state(%x).\n",
-	    instance->registers->control);
-
-	/* Use HCCA */
-	instance->registers->hcca = addr_to_phys(instance->hcca);
-
-	/* Use queues */
-	instance->registers->bulk_head =
-	    instance->lists[USB_TRANSFER_BULK].list_head_pa;
-	usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
-	    instance->lists[USB_TRANSFER_BULK].list_head,
-	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
-
-	instance->registers->control_head =
-	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
-	usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
-	    instance->lists[USB_TRANSFER_CONTROL].list_head,
-	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
-
-	/* Enable queues */
-	instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
-	usb_log_debug2("All queues enabled(%x).\n",
-	    instance->registers->control);
-
-	/* Enable interrupts */
-	instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;
-	usb_log_debug2("Enabled interrupts: %x.\n",
-	    instance->registers->interrupt_enable);
-	instance->registers->interrupt_enable = I_MI;
-
-	/* Set periodic start to 90% */
-	uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
-	instance->registers->periodic_start = (frame_length / 10) * 9;
-	usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
-	    instance->registers->periodic_start,
-	    instance->registers->periodic_start, frame_length);
-
-	instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
-	usb_log_info("OHCI HC up and running(%x).\n",
-	    instance->registers->control);
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize schedule queues
- *
- * @param[in] instance OHCI hc driver structure
- * @return Error code
- */
-int hc_init_transfer_lists(hc_t *instance)
-{
-	assert(instance);
-#define SETUP_ENDPOINT_LIST(type) \
-do { \
-	const char *name = usb_str_transfer_type(type); \
-	int ret = endpoint_list_init(&instance->lists[type], name); \
-	if (ret != EOK) { \
-		usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
-		    ret, name); \
-		endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
-		endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
-		endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
-		endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
-		return ret; \
-	} \
-} while (0)
-
-	SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
-	SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
-	SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
-	SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
-#undef SETUP_ENDPOINT_LIST
-	endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
-	    &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize memory structures used by the OHCI hcd.
- *
- * @param[in] instance OHCI hc driver structure.
- * @return Error code.
- */
-int hc_init_memory(hc_t *instance)
-{
-	assert(instance);
-
-	bzero(&instance->rh, sizeof(instance->rh));
-	/* Init queues */
-	const int ret = hc_init_transfer_lists(instance);
-	if (ret != EOK) {
-		return ret;
-	}
-
-	/*Init HCCA */
-	instance->hcca = malloc32(sizeof(hcca_t));
-	if (instance->hcca == NULL)
-		return ENOMEM;
-	bzero(instance->hcca, sizeof(hcca_t));
-	usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
-
-	unsigned i = 0;
-	for (; i < 32; ++i) {
-		instance->hcca->int_ep[i] =
-		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
-	}
-	usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
-	    instance->lists[USB_TRANSFER_INTERRUPT].list_head,
-	    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
-
-	/* Init interrupt code */
-	instance->interrupt_code.cmds = instance->interrupt_commands;
-	instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS;
-	{
-		/* Read status register */
-		instance->interrupt_commands[0].cmd = CMD_MEM_READ_32;
-		instance->interrupt_commands[0].dstarg = 1;
-		instance->interrupt_commands[0].addr =
-		    (void*)&instance->registers->interrupt_status;
-
-		/* Test whether we are the interrupt cause */
-		instance->interrupt_commands[1].cmd = CMD_BTEST;
-		instance->interrupt_commands[1].value =
-		    OHCI_USED_INTERRUPTS;
-		instance->interrupt_commands[1].srcarg = 1;
-		instance->interrupt_commands[1].dstarg = 2;
-
-		/* Predicate cleaning and accepting */
-		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
-		instance->interrupt_commands[2].value = 2;
-		instance->interrupt_commands[2].srcarg = 2;
-
-		/* Write-clean status register */
-		instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32;
-		instance->interrupt_commands[3].srcarg = 1;
-		instance->interrupt_commands[3].addr =
-		    (void*)&instance->registers->interrupt_status;
-
-		/* Accept interrupt */
-		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
-	}
-
-	return EOK;
-}
-/**
- * @}
- */
Index: pace/drv/ohci/hc.h
===================================================================
--- uspace/drv/ohci/hc.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,120 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI host controller driver structure
- */
-#ifndef DRV_OHCI_HC_H
-#define DRV_OHCI_HC_H
-
-#include <fibril.h>
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <ddi.h>
-
-#include <usb/usb.h>
-#include <usb/host/device_keeper.h>
-#include <usb/host/usb_endpoint_manager.h>
-#include <usbhc_iface.h>
-
-#include "batch.h"
-#include "ohci_regs.h"
-#include "root_hub.h"
-#include "endpoint_list.h"
-#include "hw_struct/hcca.h"
-
-#define OHCI_NEEDED_IRQ_COMMANDS 5
-
-/** Main OHCI drier structure */
-typedef struct hc {
-	/** USB bus driver, devices and addresses */
-	usb_device_keeper_t manager;
-	/** USB bus driver, endpoints */
-	usb_endpoint_manager_t ep_manager;
-
-	/** Memory mapped I/O registers area */
-	ohci_regs_t *registers;
-	/** Host controller communication area structure */
-	hcca_t *hcca;
-
-	/** Transfer schedules */
-	endpoint_list_t lists[4];
-	/** List of active transfers */
-	link_t pending_batches;
-
-	/** Fibril for periodic checks if interrupts can't be used */
-	fid_t interrupt_emulator;
-
-	/** Guards schedule and endpoint manipulation */
-	fibril_mutex_t guard;
-
-	/** Code to be executed in kernel interrupt handler */
-	irq_code_t interrupt_code;
-
-	/** Commands that form interrupt code */
-	irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS];
-
-	/** USB hub emulation structure */
-	rh_t rh;
-} hc_t;
-
-int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
-int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
-void hc_start_hw(hc_t *instance);
-
-/** Safely dispose host controller internal structures
- *
- * @param[in] instance Host controller structure to use.
- */
-static inline void hc_fini(hc_t *instance)
-	{ /* TODO: implement*/ };
-
-int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
-    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
-    size_t max_packet_size, size_t size, unsigned interval);
-int hc_remove_endpoint(hc_t *instance, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction);
-endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
-
-int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
-void hc_interrupt(hc_t *instance, uint32_t status);
-
-/** Get and cast pointer to the driver data
- *
- * @param[in] fun DDF function pointer
- * @return cast pointer to driver_data
- */
-static inline hc_t * fun_to_hc(ddf_fun_t *fun)
-	{ return fun->driver_data; }
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/hcd_endpoint.c
===================================================================
--- uspace/drv/ohci/hcd_endpoint.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,110 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#include "utils/malloc32.h"
-#include "hcd_endpoint.h"
-
-/** Callback to set toggle on ED.
- *
- * @param[in] hcd_ep hcd endpoint structure
- * @param[in] toggle new value of toggle bit
- */
-static void hcd_ep_toggle_set(void *hcd_ep, int toggle)
-{
-	hcd_endpoint_t *instance = hcd_ep;
-	assert(instance);
-	assert(instance->ed);
-	ed_toggle_set(instance->ed, toggle);
-}
-/*----------------------------------------------------------------------------*/
-/** Callback to get value of toggle bit.
- *
- * @param[in] hcd_ep hcd endpoint structure
- * @return Current value of toggle bit.
- */
-static int hcd_ep_toggle_get(void *hcd_ep)
-{
-	hcd_endpoint_t *instance = hcd_ep;
-	assert(instance);
-	assert(instance->ed);
-	return ed_toggle_get(instance->ed);
-}
-/*----------------------------------------------------------------------------*/
-/** Creates new hcd endpoint representation.
- *
- * @param[in] ep USBD endpoint structure
- * @return pointer to a new hcd endpoint structure, NULL on failure.
- */
-hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep)
-{
-	assert(ep);
-	hcd_endpoint_t *hcd_ep = malloc(sizeof(hcd_endpoint_t));
-	if (hcd_ep == NULL)
-		return NULL;
-
-	hcd_ep->ed = malloc32(sizeof(ed_t));
-	if (hcd_ep->ed == NULL) {
-		free(hcd_ep);
-		return NULL;
-	}
-
-	hcd_ep->td = malloc32(sizeof(td_t));
-	if (hcd_ep->td == NULL) {
-		free32(hcd_ep->ed);
-		free(hcd_ep);
-		return NULL;
-	}
-
-	ed_init(hcd_ep->ed, ep);
-	ed_set_td(hcd_ep->ed, hcd_ep->td);
-	endpoint_set_hc_data(ep, hcd_ep, hcd_ep_toggle_get, hcd_ep_toggle_set);
-
-	return hcd_ep;
-}
-/*----------------------------------------------------------------------------*/
-/** Disposes assigned hcd endpoint structure
- *
- * @param[in] ep USBD endpoint structure
- */
-void hcd_endpoint_clear(endpoint_t *ep)
-{
-	assert(ep);
-	hcd_endpoint_t *hcd_ep = ep->hc_data.data;
-	assert(hcd_ep);
-	free32(hcd_ep->ed);
-	free32(hcd_ep->td);
-	free(hcd_ep);
-}
-/**
- * @}
- */
Index: pace/drv/ohci/hcd_endpoint.h
===================================================================
--- uspace/drv/ohci/hcd_endpoint.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,70 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#ifndef DRV_OHCI_HCD_ENDPOINT_H
-#define DRV_OHCI_HCD_ENDPOINT_H
-
-#include <assert.h>
-#include <adt/list.h>
-#include <usb/host/endpoint.h>
-
-#include "hw_struct/endpoint_descriptor.h"
-#include "hw_struct/transfer_descriptor.h"
-
-/** Connector structure linking ED to to prepared TD. */
-typedef struct hcd_endpoint {
-	/** OHCI endpoint descriptor */
-	ed_t *ed;
-	/** Currently enqueued transfer descriptor */
-	td_t *td;
-	/** Linked list used by driver software */
-	link_t link;
-} hcd_endpoint_t;
-
-hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
-void hcd_endpoint_clear(endpoint_t *ep);
-
-/** Get and convert assigned hcd_endpoint_t structure
- * @param[in] ep USBD endpoint structure.
- * @return Pointer to assigned hcd endpoint structure
- */
-static inline hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)
-{
-	assert(ep);
-	return ep->hc_data.data;
-}
-
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/hw_struct/completion_codes.h
===================================================================
--- uspace/drv/ohci/hw_struct/completion_codes.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,91 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#ifndef DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H
-#define DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H
-
-#include <errno.h>
-
-#define CC_NOERROR (0x0)
-#define CC_CRC (0x1)
-#define CC_BITSTUFF (0x2)
-#define CC_TOGGLE (0x3)
-#define CC_STALL (0x4)
-#define CC_NORESPONSE (0x5)
-#define CC_PIDFAIL (0x6)
-#define CC_PIDUNEXPECTED (0x7)
-#define CC_DATAOVERRRUN (0x8)
-#define CC_DATAUNDERRRUN (0x9)
-#define CC_BUFFEROVERRRUN (0xc)
-#define CC_BUFFERUNDERRUN (0xd)
-#define CC_NOACCESS1 (0xe)
-#define CC_NOACCESS2 (0xf)
-
-inline static int cc_to_rc(int cc)
-{
-	switch (cc) {
-	case CC_NOERROR:
-		return EOK;
-
-	case CC_CRC:
-		return EBADCHECKSUM;
-
-	case CC_PIDUNEXPECTED:
-	case CC_PIDFAIL:
-	case CC_BITSTUFF:
-		return EIO;
-
-	case CC_TOGGLE:
-	case CC_STALL:
-		return ESTALL;
-
-	case CC_NORESPONSE:
-		return ETIMEOUT;
-
-	case CC_DATAOVERRRUN:
-	case CC_DATAUNDERRRUN:
-	case CC_BUFFEROVERRRUN:
-	case CC_BUFFERUNDERRUN:
-		return EOVERFLOW;
-
-	case CC_NOACCESS1:
-	case CC_NOACCESS2:
-	default:
-		return ENOTSUP;
-	}
-}
-
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/hw_struct/endpoint_descriptor.c
===================================================================
--- uspace/drv/ohci/hw_struct/endpoint_descriptor.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,66 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#include "endpoint_descriptor.h"
-
-static unsigned direc[3] =
-    { ED_STATUS_D_IN, ED_STATUS_D_OUT, ED_STATUS_D_TRANSFER };
-
-void ed_init(ed_t *instance, endpoint_t *ep)
-{
-	assert(instance);
-	bzero(instance, sizeof(ed_t));
-	if (ep == NULL) {
-		instance->status = ED_STATUS_K_FLAG;
-		return;
-	}
-	assert(ep);
-	instance->status = 0
-	    | ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
-	    | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)
-	    | ((direc[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)
-	    | ((ep->max_packet_size & ED_STATUS_MPS_MASK)
-	        << ED_STATUS_MPS_SHIFT);
-
-
-	if (ep->speed == USB_SPEED_LOW)
-		instance->status |= ED_STATUS_S_FLAG;
-	if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
-		instance->status |= ED_STATUS_F_FLAG;
-
-	if (ep->toggle)
-		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
-}
-/**
- * @}
- */
Index: pace/drv/ohci/hw_struct/endpoint_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/endpoint_descriptor.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,131 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#ifndef DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
-#define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
-
-#include <assert.h>
-#include <stdint.h>
-
-#include <usb/host/endpoint.h>
-
-#include "../utils/malloc32.h"
-#include "transfer_descriptor.h"
-
-#include "completion_codes.h"
-
-typedef struct ed {
-	volatile uint32_t status;
-#define ED_STATUS_FA_MASK (0x7f)   /* USB device address   */
-#define ED_STATUS_FA_SHIFT (0)
-#define ED_STATUS_EN_MASK (0xf)    /* USB endpoint address */
-#define ED_STATUS_EN_SHIFT (7)
-#define ED_STATUS_D_MASK (0x3)     /* direction */
-#define ED_STATUS_D_SHIFT (11)
-#define ED_STATUS_D_OUT (0x1)
-#define ED_STATUS_D_IN (0x2)
-#define ED_STATUS_D_TRANSFER (0x3)
-
-#define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */
-#define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */
-#define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/
-#define ED_STATUS_MPS_MASK (0x3ff) /* max_packet_size*/
-#define ED_STATUS_MPS_SHIFT (16)
-
-	volatile uint32_t td_tail;
-#define ED_TDTAIL_PTR_MASK (0xfffffff0)
-#define ED_TDTAIL_PTR_SHIFT (0)
-
-	volatile uint32_t td_head;
-#define ED_TDHEAD_PTR_MASK (0xfffffff0)
-#define ED_TDHEAD_PTR_SHIFT (0)
-#define ED_TDHEAD_ZERO_MASK (0x3)
-#define ED_TDHEAD_ZERO_SHIFT (2)
-#define ED_TDHEAD_TOGGLE_CARRY (0x2)
-#define ED_TDHEAD_HALTED_FLAG (0x1)
-
-	volatile uint32_t next;
-#define ED_NEXT_PTR_MASK (0xfffffff0)
-#define ED_NEXT_PTR_SHIFT (0)
-} __attribute__((packed)) ed_t;
-
-void ed_init(ed_t *instance, endpoint_t *ep);
-
-static inline void ed_set_td(ed_t *instance, td_t *td)
-{
-	assert(instance);
-	uintptr_t pa = addr_to_phys(td);
-	instance->td_head =
-	    ((pa & ED_TDHEAD_PTR_MASK)
-	    | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
-	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
-}
-
-static inline void ed_set_end_td(ed_t *instance, td_t *td)
-{
-	assert(instance);
-	uintptr_t pa = addr_to_phys(td);
-	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
-}
-
-static inline void ed_append_ed(ed_t *instance, ed_t *next)
-{
-	assert(instance);
-	assert(next);
-	uint32_t pa = addr_to_phys(next);
-	assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);
-	instance->next = pa;
-}
-
-static inline int ed_toggle_get(ed_t *instance)
-{
-	assert(instance);
-	return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
-}
-
-static inline void ed_toggle_set(ed_t *instance, int toggle)
-{
-	assert(instance);
-	assert(toggle == 0 || toggle == 1);
-	if (toggle == 1) {
-		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
-	} else {
-		/* clear halted flag when reseting toggle */
-		instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
-		instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
-	}
-}
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/hw_struct/hcca.h
===================================================================
--- uspace/drv/ohci/hw_struct/hcca.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#ifndef DRV_OHCI_HW_STRUCT_HCCA_H
-#define DRV_OHCI_HW_STRUCT_HCCA_H
-
-#include <stdint.h>
-
-/** Host controller communication area.
- * Shared memory used for communication between the controller and the driver.
- */
-typedef struct hcca {
-	uint32_t int_ep[32];
-	uint16_t frame_number;
-	uint16_t pad1;
-	uint32_t done_head;
-	uint32_t reserved[29];
-} __attribute__((packed, aligned)) hcca_t;
-
-#endif
-/**
- * @}
- */
-
Index: pace/drv/ohci/hw_struct/iso_transfer_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/iso_transfer_descriptor.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,75 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#ifndef DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H
-#define DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H
-
-#include <stdint.h>
-
-#include "completion_codes.h"
-
-typedef struct itd {
-	volatile uint32_t status;
-#define ITD_STATUS_SF_MASK (0xffff) /* starting frame */
-#define ITD_STATUS_SF_SHIFT (0)
-#define ITD_STATUS_DI_MASK (0x7) /* delay int, wait DI frames before int */
-#define ITD_STATUS_DI_SHIFT (21)
-#define ITD_STATUS_DI_NO_INTERRUPT (0x7)
-#define ITD_STATUS_FC_MASK (0x7) /* frame count */
-#define ITD_STATUS_FC_SHIFT (24)
-#define ITD_STATUS_CC_MASK (0xf) /* condition code */
-#define ITD_STATUS_CC_SHIFT (28)
-
-	volatile uint32_t page;   /* page number of the first byte in buffer */
-#define ITD_PAGE_BP0_MASK (0xfffff000)
-#define ITD_PAGE_BP0_SHIFT (0)
-
-	volatile uint32_t next;
-#define ITD_NEXT_PTR_MASK (0xfffffff0)
-#define ITD_NEXT_PTR_SHIFT (0)
-
-	volatile uint32_t be; /* buffer end, address of the last byte */
-
-	volatile uint16_t offset[8];
-#define ITD_OFFSET_SIZE_MASK (0x3ff)
-#define ITD_OFFSET_SIZE_SHIFT (0)
-#define ITD_OFFSET_CC_MASK (0xf)
-#define ITD_OFFSET_CC_SHIFT (12)
-
-} __attribute__((packed)) itd_t;
-#endif
-/**
- * @}
- */
-
-
Index: pace/drv/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#include <usb/usb.h>
-#include "transfer_descriptor.h"
-
-static unsigned dp[3] =
-    { TD_STATUS_DP_IN, TD_STATUS_DP_OUT, TD_STATUS_DP_SETUP };
-static unsigned togg[2] = { TD_STATUS_T_0, TD_STATUS_T_1 };
-
-void td_init(
-    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle)
-{
-	assert(instance);
-	bzero(instance, sizeof(td_t));
-	instance->status = 0
-	    | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
-	    | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
-	if (toggle == 0 || toggle == 1) {
-		instance->status |= togg[toggle] << TD_STATUS_T_SHIFT;
-	}
-	if (dir == USB_DIRECTION_IN) {
-		instance->status |= TD_STATUS_ROUND_FLAG;
-	}
-	if (buffer != NULL) {
-		assert(size != 0);
-		instance->cbp = addr_to_phys(buffer);
-		instance->be = addr_to_phys(buffer + size - 1);
-	}
-}
-/**
- * @}
- */
-
Index: pace/drv/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,118 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#ifndef DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
-#define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
-
-#include <bool.h>
-#include <stdint.h>
-#include "../utils/malloc32.h"
-
-#include "completion_codes.h"
-
-/* OHCI TDs can handle up to 8KB buffers, however, it can use max 2 pages.
- * Using 4KB buffers guarantees the page count condition.
- * (OHCI assumes 4KB pages) */
-#define OHCI_TD_MAX_TRANSFER (4 * 1024)
-
-typedef struct td {
-	volatile uint32_t status;
-#define TD_STATUS_ROUND_FLAG (1 << 18)
-#define TD_STATUS_DP_MASK (0x3) /* direction/PID */
-#define TD_STATUS_DP_SHIFT (19)
-#define TD_STATUS_DP_SETUP (0x0)
-#define TD_STATUS_DP_OUT (0x1)
-#define TD_STATUS_DP_IN (0x2)
-#define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */
-#define TD_STATUS_DI_SHIFT (21)
-#define TD_STATUS_DI_NO_INTERRUPT (0x7)
-#define TD_STATUS_T_MASK (0x3)  /* data toggle 1x = use ED toggle carry */
-#define TD_STATUS_T_SHIFT (24)
-#define TD_STATUS_T_0 (0x2)
-#define TD_STATUS_T_1 (0x3)
-#define TD_STATUS_T_ED (0)
-#define TD_STATUS_EC_MASK (0x3) /* error count */
-#define TD_STATUS_EC_SHIFT (26)
-#define TD_STATUS_CC_MASK (0xf) /* condition code */
-#define TD_STATUS_CC_SHIFT (28)
-
-	volatile uint32_t cbp; /* current buffer ptr, data to be transfered */
-	volatile uint32_t next;
-#define TD_NEXT_PTR_MASK (0xfffffff0)
-#define TD_NEXT_PTR_SHIFT (0)
-
-	volatile uint32_t be; /* buffer end, address of the last byte */
-} __attribute__((packed)) td_t;
-
-void td_init(
-    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);
-
-inline static void td_set_next(td_t *instance, td_t *next)
-{
-	assert(instance);
-	instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
-}
-
-inline static bool td_is_finished(td_t *instance)
-{
-	assert(instance);
-	int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
-	/* something went wrong, error code is set */
-	if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
-		return true;
-	}
-	/* everything done */
-	if (cc == CC_NOERROR && instance->cbp == 0) {
-		return true;
-	}
-	return false;
-}
-
-static inline int td_error(td_t *instance)
-{
-	assert(instance);
-	int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
-	return cc_to_rc(cc);
-}
-
-static inline size_t td_remain_size(td_t *instance)
-{
-	assert(instance);
-	if (instance->cbp == 0)
-		return 0;
-	return instance->be - instance->cbp + 1;
-}
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/iface.c
===================================================================
--- uspace/drv/ohci/iface.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,441 +1,0 @@
-/*
- * Copyright (c) 2011 Vojtech Horky, Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver hc interface implementation
- */
-#include <ddf/driver.h>
-#include <errno.h>
-
-#include <usb/debug.h>
-#include <usb/host/endpoint.h>
-
-#include "iface.h"
-#include "hc.h"
-
-static inline int setup_batch(
-    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
-    void *data, size_t size, void * setup_data, size_t setup_size,
-    usbhc_iface_transfer_in_callback_t in,
-    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
-    hc_t **hc, usb_transfer_batch_t **batch)
-{
-	assert(hc);
-	assert(batch);
-	assert(fun);
-	*hc = fun_to_hc(fun);
-	assert(*hc);
-
-	size_t res_bw;
-	endpoint_t *ep = hc_get_endpoint(*hc,
-	    target.address, target.endpoint, direction, &res_bw);
-	if (ep == NULL) {
-		usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
-		    target.address, target.endpoint, name);
-		return ENOENT;
-	}
-
-	usb_log_debug("%s %d:%d %zu(%zu).\n",
-	    name, target.address, target.endpoint, size, ep->max_packet_size);
-
-	const size_t bw = bandwidth_count_usb11(
-	    ep->speed, ep->transfer_type, size, ep->max_packet_size);
-	if (res_bw < bw) {
-		usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
-		    "but only %zu is reserved.\n",
-		    target.address, target.endpoint, name, bw, res_bw);
-		return ENOSPC;
-	}
-
-	*batch = batch_get(
-	    fun, ep, data, size, setup_data, setup_size, in, out, arg);
-	if (!*batch)
-		return ENOMEM;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Request address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] speed Speed to associate with the new default address.
- * @param[out] address Place to write a new address.
- * @return Error code.
- */
-static int request_address(
-    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	assert(address);
-
-	usb_log_debug("Address request with speed %d.\n", speed);
-	*address = device_keeper_get_free_address(&hc->manager, speed);
-	usb_log_debug("Address request with result: %d.\n", *address);
-	if (*address <= 0)
-		return *address;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Bind address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address Address of the device
- * @param[in] handle Devman handle of the device driver.
- * @return Error code.
- */
-static int bind_address(
-  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
-	usb_device_keeper_bind(&hc->manager, address, handle);
-	return EOK;
-}
-
-
-/** Find device handle by address interface function.
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address Address in question.
- * @param[out] handle Where to store device handle if found.
- * @return Error code.
- */
-static int find_by_address(ddf_fun_t *fun, usb_address_t address,
-    devman_handle_t *handle)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	bool found =
-	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
-	return found ? EOK : ENOENT;
-}
-
-/*----------------------------------------------------------------------------*/
-/** Release address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address USB address to be released.
- * @return Error code.
- */
-static int release_address(ddf_fun_t *fun, usb_address_t address)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	usb_log_debug("Address release %d.\n", address);
-	usb_device_keeper_release(&hc->manager, address);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Register endpoint for bandwidth reservation.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address of the device.
- * @param[in] ep_speed Endpoint speed (invalid means to use device one).
- * @param[in] endpoint Endpoint number.
- * @param[in] transfer_type USB transfer type.
- * @param[in] direction Endpoint data direction.
- * @param[in] max_packet_size Max packet size of the endpoint.
- * @param[in] interval Polling interval.
- * @return Error code.
- */
-static int register_endpoint(ddf_fun_t *fun,
-    usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,
-    usb_transfer_type_t transfer_type, usb_direction_t direction,
-    size_t max_packet_size, unsigned int interval)
-{
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-
-	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
-	if (speed >= USB_SPEED_MAX) {
-		speed = ep_speed;
-	}
-	const size_t size = max_packet_size;
-
-	usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
-	    address, endpoint, usb_str_transfer_type(transfer_type),
-	    usb_str_speed(speed), direction, size, max_packet_size, interval);
-
-	return hc_add_endpoint(hc, address, endpoint, speed, transfer_type,
-	    direction, max_packet_size, size, interval);
-}
-/*----------------------------------------------------------------------------*/
-static int unregister_endpoint(
-    ddf_fun_t *fun, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction)
-{
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	usb_log_debug("Unregister endpoint %d:%d %d.\n",
-	    address, endpoint, direction);
-	return hc_remove_endpoint(hc, address, endpoint, direction);
-}
-/*----------------------------------------------------------------------------*/
-/** Schedule interrupt out transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
- *	by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int interrupt_out(
-    ddf_fun_t *fun, usb_target_t target, void *data,
-    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
-	    NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	batch_interrupt_out(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Schedule interrupt in transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int interrupt_in(
-    ddf_fun_t *fun, usb_target_t target, void *data,
-    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
-	    NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	batch_interrupt_in(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Schedule bulk out transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
- *	by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int bulk_out(
-    ddf_fun_t *fun, usb_target_t target, void *data,
-    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
-	    NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	batch_bulk_out(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Schedule bulk in transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int bulk_in(
-    ddf_fun_t *fun, usb_target_t target, void *data,
-    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
-	    NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	batch_bulk_in(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Schedule control write transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
- *	and deallocated by the caller).
- * @param[in] setup_size Size of @p setup_packet buffer in bytes.
- * @param[in] data_buffer Data buffer (in USB endianess, allocated and
- *	deallocated by the caller).
- * @param[in] size Size of @p data_buffer buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int control_write(
-    ddf_fun_t *fun, 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)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
-	    setup_data, setup_size, NULL, callback, arg, "Control WRITE",
-	    &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
-	batch_control_write(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Schedule control read transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
- *	and deallocated by the caller).
- * @param[in] setup_size Size of @p setup_packet buffer in bytes.
- * @param[in] data_buffer Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] size Size of @p data_buffer buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int control_read(
-    ddf_fun_t *fun, 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)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
-	    setup_data, setup_size, callback, NULL, arg, "Control READ",
-	    &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	batch_control_read(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-usbhc_iface_t hc_iface = {
-	.request_address = request_address,
-	.bind_address = bind_address,
-	.find_by_address = find_by_address,
-	.release_address = release_address,
-
-	.register_endpoint = register_endpoint,
-	.unregister_endpoint = unregister_endpoint,
-
-	.interrupt_out = interrupt_out,
-	.interrupt_in = interrupt_in,
-
-	.bulk_out = bulk_out,
-	.bulk_in = bulk_in,
-
-	.control_write = control_write,
-	.control_read = control_read,
-};
-/**
- * @}
- */
Index: pace/drv/ohci/iface.h
===================================================================
--- uspace/drv/ohci/iface.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * 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 drvusbohci
- * @{
- */
-/** @file
- * Common OHCI definitions.
- */
-#ifndef DRV_OHCI_IFACE_H
-#define DRV_OHCI_IFACE_H
-
-#include <usbhc_iface.h>
-
-extern usbhc_iface_t hc_iface;
-
-#endif
-/**
- * @}
- */
-
Index: pace/drv/ohci/main.c
===================================================================
--- uspace/drv/ohci/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,90 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * 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 drvusbohci
- * @{
- */
-/** @file
- * Main routines of OHCI driver.
- */
-#include <ddf/driver.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/debug.h>
-
-#include "ohci.h"
-
-#define NAME "ohci"
-
-/** Initializes a new ddf driver instance of OHCI hcd.
- *
- * @param[in] device DDF instance of the device to initialize.
- * @return Error code.
- */
-static int ohci_add_device(ddf_dev_t *device)
-{
-	usb_log_debug("ohci_add_device() called\n");
-	assert(device);
-
-	int ret = device_setup_ohci(device);
-	if (ret != EOK) {
-		usb_log_error("Failed to initialize OHCI driver: %s.\n",
-		    str_error(ret));
-		return ret;
-	}
-	usb_log_info("Controlling new OHCI device '%s'.\n", device->name);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static driver_ops_t ohci_driver_ops = {
-	.add_device = ohci_add_device,
-};
-/*----------------------------------------------------------------------------*/
-static driver_t ohci_driver = {
-	.name = NAME,
-	.driver_ops = &ohci_driver_ops
-};
-/*----------------------------------------------------------------------------*/
-/** Initializes global driver structures (NONE).
- *
- * @param[in] argc Nmber of arguments in argv vector (ignored).
- * @param[in] argv Cmdline argument vector (ignored).
- * @return Error code.
- *
- * Driver debug level is set here.
- */
-int main(int argc, char *argv[])
-{
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-	return ddf_driver_main(&ohci_driver);
-}
-/**
- * @}
- */
Index: pace/drv/ohci/ohci.c
===================================================================
--- uspace/drv/ohci/ohci.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,247 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/interrupt.h>
-#include <usb_iface.h>
-#include <usb/usb.h>
-#include <usb/ddfiface.h>
-#include <usb/debug.h>
-
-#include "ohci.h"
-#include "iface.h"
-#include "pci.h"
-#include "hc.h"
-#include "root_hub.h"
-
-typedef struct ohci {
-	ddf_fun_t *hc_fun;
-	ddf_fun_t *rh_fun;
-
-	hc_t hc;
-	rh_t rh;
-} ohci_t;
-
-static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
-{
-	assert(dev);
-	assert(dev->driver_data);
-	return dev->driver_data;
-}
-
-/** IRQ handling callback, identifies device
- *
- * @param[in] dev DDF instance of the device to use.
- * @param[in] iid (Unused).
- * @param[in] call Pointer to the call that represents interrupt.
- */
-static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
-{
-	hc_t *hc = &dev_to_ohci(dev)->hc;
-	assert(hc);
-	const uint16_t status = IPC_GET_ARG1(*call);
-	hc_interrupt(hc, status);
-}
-/*----------------------------------------------------------------------------*/
-/** Get address of the device identified by handle.
- *
- * @param[in] dev DDF instance of the device to use.
- * @param[in] iid (Unused).
- * @param[in] call Pointer to the call that represents interrupt.
- */
-static int usb_iface_get_address(
-    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
-{
-	assert(fun);
-	usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager;
-
-	usb_address_t addr = usb_device_keeper_find(manager, handle);
-	if (addr < 0) {
-		return addr;
-	}
-
-	if (address != NULL) {
-		*address = addr;
-	}
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Gets handle of the respective hc (this device, hc function).
- *
- * @param[in] root_hub_fun Root hub function seeking hc handle.
- * @param[out] handle Place to write the handle.
- * @return Error code.
- */
-static int usb_iface_get_hc_handle(
-    ddf_fun_t *fun, devman_handle_t *handle)
-{
-	assert(fun);
-	ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
-	assert(hc_fun);
-
-	if (handle != NULL)
-		*handle = hc_fun->handle;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Root hub USB interface */
-static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle,
-	.get_address = usb_iface_get_address
-};
-/*----------------------------------------------------------------------------*/
-/** Standard USB HC options (HC interface) */
-static ddf_dev_ops_t hc_ops = {
-	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
-};
-/*----------------------------------------------------------------------------*/
-/** Standard USB RH options (RH interface) */
-static ddf_dev_ops_t rh_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface,
-};
-/*----------------------------------------------------------------------------*/
-/** Initialize hc and rh ddf structures and their respective drivers.
- *
- * @param[in] device DDF instance of the device to use.
- * @param[in] instance OHCI structure to use.
- *
- * This function does all the preparatory work for hc and rh drivers:
- *  - gets device hw resources
- *  - disables OHCI legacy support
- *  - asks for interrupt
- *  - registers interrupt handler
- */
-int device_setup_ohci(ddf_dev_t *device)
-{
-	ohci_t *instance = malloc(sizeof(ohci_t));
-	if (instance == NULL) {
-		usb_log_error("Failed to allocate OHCI driver.\n");
-		return ENOMEM;
-	}
-
-#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
-if (ret != EOK) { \
-	if (instance->hc_fun) { \
-		instance->hc_fun->ops = NULL; \
-		instance->hc_fun->driver_data = NULL; \
-		ddf_fun_destroy(instance->hc_fun); \
-	} \
-	if (instance->rh_fun) { \
-		instance->rh_fun->ops = NULL; \
-		instance->rh_fun->driver_data = NULL; \
-		ddf_fun_destroy(instance->rh_fun); \
-	} \
-	free(instance); \
-	usb_log_error(message); \
-	return ret; \
-} else (void)0
-
-	instance->rh_fun = NULL;
-	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
-	int ret = instance->hc_fun ? EOK : ENOMEM;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n");
-	instance->hc_fun->ops = &hc_ops;
-	instance->hc_fun->driver_data = &instance->hc;
-
-	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
-	ret = instance->rh_fun ? EOK : ENOMEM;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n");
-	instance->rh_fun->ops = &rh_ops;
-
-	uintptr_t reg_base = 0;
-	size_t reg_size = 0;
-	int irq = 0;
-
-	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed to get memory addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
-	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
-	    (void *) reg_base, reg_size, irq);
-
-	bool interrupts = false;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, "
-	    "falling back to polling.\n");
-#else
-	ret = pci_enable_interrupts(device);
-	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
-		    str_error(ret));
-		usb_log_info("HW interrupts not available, "
-		    "falling back to polling.\n");
-	} else {
-		usb_log_debug("Hw interrupts enabled.\n");
-		interrupts = true;
-	}
-#endif
-
-	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci_hcd.\n", ret);
-
-#define CHECK_RET_FINI_RETURN(ret, message...) \
-if (ret != EOK) { \
-	hc_fini(&instance->hc); \
-	CHECK_RET_DEST_FREE_RETURN(ret, message); \
-} else (void)0
-
-	/* It does no harm if we register this on polling */
-	ret = register_interrupt_handler(device, irq, irq_handler,
-	    &instance->hc.interrupt_code);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register interrupt handler.\n", ret);
-
-	ret = ddf_fun_bind(instance->hc_fun);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to bind OHCI device function: %s.\n",
-	    ret, str_error(ret));
-
-	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
-
-	device->driver_data = instance;
-
-	hc_start_hw(&instance->hc);
-	hc_register_hub(&instance->hc, instance->rh_fun);
-	return EOK;
-
-#undef CHECK_RET_DEST_FUN_RETURN
-#undef CHECK_RET_FINI_RETURN
-}
-/**
- * @}
- */
Index: pace/drv/ohci/ohci.h
===================================================================
--- uspace/drv/ohci/ohci.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver main structure for both host controller and root-hub.
- */
-#ifndef DRV_OHCI_OHCI_H
-#define DRV_OHCI_OHCI_H
-#include <ddi.h>
-#include <ddf/driver.h>
-
-int device_setup_ohci(ddf_dev_t *device);
-
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/ohci.ma
===================================================================
--- uspace/drv/ohci/ohci.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,14 +1,0 @@
-10 pci/ven=106b&dev=003f
-10 pci/ven=10de&dev=0aa5
-
-10 pci/ven=1002&dev=4374
-10 pci/ven=1002&dev=4375
-
-10 pci/ven=1002&dev=4387
-10 pci/ven=1002&dev=4388
-10 pci/ven=1002&dev=4389
-10 pci/ven=1002&dev=438a
-10 pci/ven=1002&dev=438b
-10 pci/ven=1002&dev=4397
-10 pci/ven=1002&dev=4398
-10 pci/ven=1002&dev=4399
Index: pace/drv/ohci/ohci_regs.h
===================================================================
--- uspace/drv/ohci/ohci_regs.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,219 +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 drvusbohcihc
- * @{
- */
-/** @file
- * @brief OHCI host controller register structure
- */
-#ifndef DRV_OHCI_OHCI_REGS_H
-#define DRV_OHCI_OHCI_REGS_H
-#include <stdint.h>
-
-/** OHCI memory mapped registers structure */
-typedef struct ohci_regs {
-	const volatile uint32_t revision;
-	volatile uint32_t control;
-#define C_CSBR_MASK (0x3) /* Control-bulk service ratio */
-#define C_CSBR_1_1  (0x0)
-#define C_CSBR_1_2  (0x1)
-#define C_CSBR_1_3  (0x2)
-#define C_CSBR_1_4  (0x3)
-#define C_CSBR_SHIFT (0)
-
-#define C_PLE (1 << 2)   /* Periodic list enable */
-#define C_IE  (1 << 3)   /* Isochronous enable */
-#define C_CLE (1 << 4)   /* Control list enable */
-#define C_BLE (1 << 5)   /* Bulk list enable */
-
-#define C_HCFS_MASK        (0x3) /* Host controller functional state */
-#define C_HCFS_RESET       (0x0)
-#define C_HCFS_RESUME      (0x1)
-#define C_HCFS_OPERATIONAL (0x2)
-#define C_HCFS_SUSPEND     (0x3)
-#define C_HCFS_SHIFT       (6)
-
-#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
-#define C_RWC (1 << 9)   /* Remote wakeup connected, host specific */
-#define C_RWE (1 << 10)  /* Remote wakeup enable */
-
-	volatile uint32_t command_status;
-#define CS_HCR (1 << 0)   /* Host controller reset */
-#define CS_CLF (1 << 1)   /* Control list filled */
-#define CS_BLF (1 << 2)   /* Bulk list filled */
-#define CS_OCR (1 << 3)   /* Ownership change request */
-#define CS_SOC_MASK (0x3) /* Scheduling overrun count */
-#define CS_SOC_SHIFT (16)
-
-	/** Interupt enable/disable/status,
-	 * reads give the same value,
-	 * writing causes enable/disable,
-	 * status is write-clean (writing 1 clears the bit*/
-	volatile uint32_t interrupt_status;
-	volatile uint32_t interrupt_enable;
-	volatile uint32_t interrupt_disable;
-#define I_SO   (1 << 0)   /* Scheduling overrun */
-#define I_WDH  (1 << 1)   /* Done head write-back */
-#define I_SF   (1 << 2)   /* Start of frame */
-#define I_RD   (1 << 3)   /* Resume detect */
-#define I_UE   (1 << 4)   /* Unrecoverable error */
-#define I_FNO  (1 << 5)   /* Frame number overflow */
-#define I_RHSC (1 << 6)   /* Root hub status change */
-#define I_OC   (1 << 30)  /* Ownership change */
-#define I_MI   (1 << 31)  /* Master interrupt (all/any interrupts) */
-
-	/** HCCA pointer (see hw_struct hcca.h) */
-	volatile uint32_t hcca;
-#define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
-
-	/** Currently executed periodic endpoint */
-	const volatile uint32_t periodic_current;
-
-	/** The first control endpoint */
-	volatile uint32_t control_head;
-
-	/** Currently executed control endpoint */
-	volatile uint32_t control_current;
-
-	/** The first bulk endpoint */
-	volatile uint32_t bulk_head;
-
-	/** Currently executed bulk endpoint */
-	volatile uint32_t bulk_current;
-
-	/** Done TD list, this value is periodically written to HCCA */
-	const volatile uint32_t done_head;
-
-	/** Frame time and max packet size for all transfers */
-	volatile uint32_t fm_interval;
-#define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/
-#define FMI_FI_SHIFT (0)
-#define FMI_FSMPS_MASK (0x7fff) /* Full speed max packet size */
-#define FMI_FSMPS_SHIFT (16)
-#define FMI_TOGGLE_FLAG (1 << 31)
-
-	/** Bit times remaining in current frame */
-	const volatile uint32_t fm_remaining;
-#define FMR_FR_MASK FMI_FI_MASK
-#define FMR_FR_SHIFT FMI_FI_SHIFT
-#define FMR_TOGGLE_FLAG FMI_TOGGLE_FLAG
-
-	/** Frame number */
-	const volatile uint32_t fm_number;
-#define FMN_NUMBER_MASK (0xffff)
-
-	/** Remaining bit time in frame to start periodic transfers */
-	volatile uint32_t periodic_start;
-#define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
-
-	/** Threshold for starting LS transaction */
-	volatile uint32_t ls_threshold;
-#define LST_LST_MASK (0x7fff)
-
-	/** The first root hub control register */
-	volatile uint32_t rh_desc_a;
-#define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
-#define RHDA_NDS_SHIFT (0)
-#define RHDA_PSM_FLAG  (1 << 8)  /* Power switching mode: 0-global, 1-per port*/
-#define RHDA_NPS_FLAG  (1 << 9)  /* No power switch: 1-power on, 0-use PSM*/
-#define RHDA_DT_FLAG   (1 << 10) /* 1-Compound device, must be 0 */
-#define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */
-#define RHDA_NOCP      (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
-#define RHDA_POTPGT_MASK (0xff)  /* Power on to power good time */
-#define RHDA_POTPGT_SHIFT (24)
-
-	/** The other root hub control register */
-	volatile uint32_t rh_desc_b;
-#define RHDB_DR_MASK (0xffff) /* Device removable mask */
-#define RHDB_DR_SHIFT (0)
-#define RHDB_PCC_MASK (0xffff) /* Power control mask */
-#define RHDB_PCC_SHIFT (16)
-
-/* Port device removable status */
-#define RHDB_DR_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
-/* Port power control status: 1-per port power control, 0-global power switch */
-#define RHDB_PPC_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
-
-	/** Root hub status register */
-	volatile uint32_t rh_status;
-#define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
-                                * write: 0-no effect,
-                                *        1-turn off port power for ports
-                                *        specified in PPCM(RHDB), or all ports,
-                                *        if power is set globally */
-#define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */
-#define RHS_OCI_FLAG  (1 <<  1)/* Over-current indicator, if per-port: 0 */
-#define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC
-                                *       1-connect status change wakes HC
-                                * write: 1-set DRWE, 0-no effect */
-#define RHS_SET_DRWE RHS_DRWE_FLAG
-#define RHS_LPSC_FLAG (1 << 16)/* read: 0,
-                                * write: 0-no effect
-                                *        1-turn on port power for ports
-                                *        specified in PPCM(RHDB), or all ports,
-                                *        if power is set globally */
-#define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */
-#define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
-#define RHS_CLEAR_DRWE (1 << 31)
-
-	/** Root hub per port status */
-	volatile uint32_t rh_port_status[];
-#define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
-                                * w: 1-clear port enable, 0-nothing */
-#define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG
-#define RHPS_PES_FLAG (1 << 1) /* r: port enable status
-                                * w: 1-set port enable, 0-nothing */
-#define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG
-#define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status
-                                * w: 1-set port suspend, 0-nothing */
-#define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG
-#define RHPS_POCI_FLAG (1 << 3) /* r: port over-current (if reports are per-port
-                                 * w: 1-clear port suspend (start resume
-                                 *      if suspened)
-                                 *    0-nothing */
-#define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG
-#define RHPS_PRS_FLAG (1 << 4) /* r: port reset status
-                                * w: 1-set port reset, 0-nothing */
-#define RHPS_SET_PORT_RESET RHPS_PRS_FLAG
-#define RHPS_PPS_FLAG (1 << 8) /* r: port power status
-                                * w: 1-set port power, 0-nothing */
-#define RHPS_SET_PORT_POWER RHPS_PPS_FLAG
-#define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached
-                                 * w: 1-clear port power, 0-nothing */
-#define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG
-#define RHPS_CSC_FLAG  (1 << 16) /* connect status change Write-Clean */
-#define RHPS_PESC_FLAG (1 << 17) /* port enable status change WC */
-#define RHPS_PSSC_FLAG (1 << 18) /* port suspend status change WC */
-#define RHPS_OCIC_FLAG (1 << 19) /* port over-current change WC */
-#define RHPS_PRSC_FLAG (1 << 20) /* port reset status change WC */
-#define RHPS_CHANGE_WC_MASK 0x1f0000
-} __attribute__((packed)) ohci_regs_t;
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/pci.c
===================================================================
--- uspace/drv/ohci/pci.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,143 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup drvusbohci
- * @{
- */
-/**
- * @file
- * PCI related functions needed by the OHCI driver.
- */
-
-#include <errno.h>
-#include <assert.h>
-#include <as.h>
-#include <devman.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-#include <device/hw_res.h>
-
-#include <usb/debug.h>
-#include <pci_dev_iface.h>
-
-#include "pci.h"
-
-/** Get address of registers and IRQ for given device.
- *
- * @param[in] dev Device asking for the addresses.
- * @param[out] mem_reg_address Base address of the memory range.
- * @param[out] mem_reg_size Size of the memory range.
- * @param[out] irq_no IRQ assigned to the device.
- * @return Error code.
- */
-int pci_get_my_registers(ddf_dev_t *dev,
-    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
-{
-	assert(dev);
-	assert(mem_reg_address);
-	assert(mem_reg_size);
-	assert(irq_no);
-
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	hw_resource_list_t hw_resources;
-	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
-	if (rc != EOK) {
-		async_hangup(parent_sess);
-		return rc;
-	}
-	
-	uintptr_t mem_address = 0;
-	size_t mem_size = 0;
-	bool mem_found = false;
-	
-	int irq = 0;
-	bool irq_found = false;
-	
-	size_t i;
-	for (i = 0; i < hw_resources.count; i++) {
-		hw_resource_t *res = &hw_resources.resources[i];
-		switch (res->type) {
-		case INTERRUPT:
-			irq = res->res.interrupt.irq;
-			irq_found = true;
-			usb_log_debug2("Found interrupt: %d.\n", irq);
-			break;
-		case MEM_RANGE:
-			if (res->res.mem_range.address != 0
-			    && res->res.mem_range.size != 0 ) {
-				mem_address = res->res.mem_range.address;
-				mem_size = res->res.mem_range.size;
-				usb_log_debug2("Found mem: %p %zu.\n",
-				    (void *) mem_address, mem_size);
-				mem_found = true;
-			}
-		default:
-			break;
-		}
-	}
-	
-	if (mem_found && irq_found) {
-		*mem_reg_address = mem_address;
-		*mem_reg_size = mem_size;
-		*irq_no = irq;
-		rc = EOK;
-	} else
-		rc = ENOENT;
-	
-	async_hangup(parent_sess);
-	return rc;
-}
-
-/** Call the PCI driver with a request to enable interrupts
- *
- * @param[in] device Device asking for interrupts
- * @return Error code.
- */
-int pci_enable_interrupts(ddf_dev_t *device)
-{
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	bool enabled = hw_res_enable_interrupt(parent_sess);
-	async_hangup(parent_sess);
-	
-	return enabled ? EOK : EIO;
-}
-
-/**
- * @}
- */
Index: pace/drv/ohci/pci.h
===================================================================
--- uspace/drv/ohci/pci.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * 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 drvusbohci
- * @{
- */
-/** @file
- * PCI related functions needed by OHCI driver.
- */
-#ifndef DRV_OHCI_PCI_H
-#define DRV_OHCI_PCI_H
-
-#include <ddf/driver.h>
-
-int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
-int pci_enable_interrupts(ddf_dev_t *);
-int pci_disable_legacy(ddf_dev_t *);
-
-#endif
-/**
- * @}
- */
-
Index: pace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,944 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#include <assert.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/debug.h>
-
-#include "root_hub.h"
-#include <usb/classes/classes.h>
-#include <usb/dev/driver.h>
-#include "ohci_regs.h"
-
-#include <usb/dev/request.h>
-#include <usb/classes/hub.h>
-
-/**
- * standart device descriptor for ohci root hub
- */
-static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = {
-	.configuration_count = 1,
-	.descriptor_type = USB_DESCTYPE_DEVICE,
-	.device_class = USB_CLASS_HUB,
-	.device_protocol = 0,
-	.device_subclass = 0,
-	.device_version = 0,
-	.length = sizeof (usb_standard_device_descriptor_t),
-	.max_packet_size = 8,
-	.vendor_id = 0x16db,
-	.product_id = 0x0001,
-	.str_serial_number = 0,
-	.usb_spec_version = 0x110,
-};
-
-/**
- * standart configuration descriptor with filled common values
- * for ohci root hubs
- */
-static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = {
-	.attributes = 1 << 7,
-	.configuration_number = 1,
-	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
-	.interface_count = 1,
-	.length = sizeof (usb_standard_configuration_descriptor_t),
-	.max_power = 100,
-	.str_configuration = 0,
-};
-
-/**
- * standart ohci root hub interface descriptor
- */
-static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = {
-	.alternate_setting = 0,
-	.descriptor_type = USB_DESCTYPE_INTERFACE,
-	.endpoint_count = 1,
-	.interface_class = USB_CLASS_HUB,
-	.interface_number = 1,
-	.interface_protocol = 0,
-	.interface_subclass = 0,
-	.length = sizeof (usb_standard_interface_descriptor_t),
-	.str_interface = 0,
-};
-
-/**
- * standart ohci root hub endpoint descriptor
- */
-static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = {
-	.attributes = USB_TRANSFER_INTERRUPT,
-	.descriptor_type = USB_DESCTYPE_ENDPOINT,
-	.endpoint_address = 1 + (1 << 7),
-	.length = sizeof (usb_standard_endpoint_descriptor_t),
-	.max_packet_size = 8,
-	.poll_interval = 255,
-};
-
-/**
- * bitmask of hub features that are valid to be cleared
- */
-static const uint32_t hub_clear_feature_valid_mask =
-    RHS_OCIC_FLAG |
-    RHS_CLEAR_PORT_POWER;
-
-/**
- * bitmask of hub features that are cleared by writing 1 (and not 0)
- */
-static const uint32_t hub_clear_feature_by_writing_one_mask =
-    RHS_CLEAR_PORT_POWER;
-
-/**
- * bitmask of hub features that are valid to be set
- */
-static const uint32_t hub_set_feature_valid_mask =
-    RHS_LPSC_FLAG |
-    RHS_OCIC_FLAG;
-
-/**
- * bitmask of hub features that are set by writing 1 and cleared by writing 0
- */
-static const uint32_t hub_set_feature_direct_mask =
-    RHS_SET_PORT_POWER;
-
-/**
- * bitmask of port features that are valid to be set
- */
-static const uint32_t port_set_feature_valid_mask =
-    RHPS_SET_PORT_ENABLE |
-    RHPS_SET_PORT_SUSPEND |
-    RHPS_SET_PORT_RESET |
-    RHPS_SET_PORT_POWER;
-
-/**
- * bitmask of port features that can be cleared
- */
-static const uint32_t port_clear_feature_valid_mask =
-    RHPS_CCS_FLAG |
-    RHPS_SET_PORT_SUSPEND |
-    RHPS_POCI_FLAG |
-    RHPS_SET_PORT_POWER |
-    RHPS_CSC_FLAG |
-    RHPS_PESC_FLAG |
-    RHPS_PSSC_FLAG |
-    RHPS_OCIC_FLAG |
-    RHPS_PRSC_FLAG;
-
-//note that USB_HUB_FEATURE_PORT_POWER bit is translated into
-//USB_HUB_FEATURE_PORT_LOW_SPEED for port set feature request
-
-/**
- * bitmask with port status changes
- */
-static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK;
-
-static int create_serialized_hub_descriptor(rh_t *instance);
-
-static int rh_init_descriptors(rh_t *instance);
-
-static int process_get_port_status_request(rh_t *instance, uint16_t port,
-    usb_transfer_batch_t * request);
-
-static int process_get_hub_status_request(rh_t *instance,
-    usb_transfer_batch_t * request);
-
-static int process_get_status_request(rh_t *instance,
-    usb_transfer_batch_t * request);
-
-static void create_interrupt_mask_in_instance(rh_t *instance);
-
-static int process_get_descriptor_request(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_get_configuration_request(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
-
-static int process_hub_feature_clear_request(rh_t *instance,
-    uint16_t feature);
-
-static int process_port_feature_set_request(rh_t *instance,
-    uint16_t feature, uint16_t port);
-
-static int process_port_feature_clear_request(rh_t *instance,
-    uint16_t feature, uint16_t port);
-
-static int process_address_set_request(rh_t *instance,
-    uint16_t address);
-
-static int process_request_with_output(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_request_with_input(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_request_without_data(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
-
-static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
-
-static bool is_zeros(void * buffer, size_t size);
-
-/** Root hub initialization
- * @return Error code.
- */
-int rh_init(rh_t *instance, ohci_regs_t *regs) {
-	assert(instance);
-	instance->registers = regs;
-	instance->port_count =
-	    (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
-	int opResult = rh_init_descriptors(instance);
-	if (opResult != EOK) {
-		return opResult;
-	}
-	// set port power mode to no-power-switching
-	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
-	instance->unfinished_interrupt_transfer = NULL;
-	instance->interrupt_mask_size = (instance->port_count + 8) / 8;
-	instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
-	if (!instance->interrupt_buffer)
-		return ENOMEM;
-
-	usb_log_info("OHCI root hub with %zu ports initialized.\n",
-	    instance->port_count);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process root hub request
- *
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
-	assert(instance);
-	assert(request);
-	int opResult;
-	if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
-		usb_log_info("Root hub got CONTROL packet\n");
-		opResult = process_ctrl_request(instance, request);
-		usb_transfer_batch_finish_error(request, opResult);
-	} else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
-		usb_log_info("Root hub got INTERRUPT packet\n");
-		create_interrupt_mask_in_instance(instance);
-		if (is_zeros(instance->interrupt_buffer,
-		    instance->interrupt_mask_size)) {
-			usb_log_debug("No changes..\n");
-			instance->unfinished_interrupt_transfer = request;
-			//will be finished later
-		} else {
-			usb_log_debug("Processing changes..\n");
-			process_interrupt_mask_in_instance(instance, request);
-		}
-		opResult = EOK;
-	} else {
-
-		opResult = EINVAL;
-		usb_transfer_batch_finish_error(request, opResult);
-	}
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * process interrupt on a hub
- *
- * If there is no pending interrupt transfer, nothing happens.
- * @param instance
- */
-void rh_interrupt(rh_t *instance) {
-	if (!instance->unfinished_interrupt_transfer) {
-		return;
-	}
-	usb_log_debug("Finalizing interrupt transfer\n");
-	create_interrupt_mask_in_instance(instance);
-	process_interrupt_mask_in_instance(instance,
-	    instance->unfinished_interrupt_transfer);
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * Create hub descriptor used in hub-driver <-> hub communication
- *
- * This means creating byt array from data in root hub registers. For more
- * info see usb hub specification.
- *
- * @param instance root hub instance
- * @return error code
- */
-static int create_serialized_hub_descriptor(rh_t *instance) {
-	size_t size = 7 +
-	    ((instance->port_count + 7) / 8) * 2;
-	size_t var_size = (instance->port_count + 7) / 8;
-	uint8_t * result = (uint8_t*) malloc(size);
-	if (!result) return ENOMEM;
-
-	bzero(result, size);
-	//size
-	result[0] = size;
-	//descriptor type
-	result[1] = USB_DESCTYPE_HUB;
-	result[2] = instance->port_count;
-	uint32_t hub_desc_reg = instance->registers->rh_desc_a;
-	result[3] =
-	    ((hub_desc_reg >> 8) % 2) +
-	    (((hub_desc_reg >> 9) % 2) << 1) +
-	    (((hub_desc_reg >> 10) % 2) << 2) +
-	    (((hub_desc_reg >> 11) % 2) << 3) +
-	    (((hub_desc_reg >> 12) % 2) << 4);
-	result[4] = 0;
-	result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
-	result[6] = 50;
-
-	size_t port;
-	for (port = 1; port <= instance->port_count; ++port) {
-		uint8_t is_non_removable =
-		    instance->registers->rh_desc_b >> port % 2;
-		result[7 + port / 8] +=
-		    is_non_removable << (port % 8);
-	}
-	size_t i;
-	for (i = 0; i < var_size; ++i) {
-		result[7 + var_size + i] = 255;
-	}
-	instance->hub_descriptor = result;
-	instance->descriptor_size = size;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/** initialize hub descriptors
- *
- * Initialized are device and full configuration descriptor. These need to
- * be initialized only once per hub.
- * @instance root hub instance
- * @return error code
- */
-static int rh_init_descriptors(rh_t *instance) {
-	memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
-	    sizeof (ohci_rh_device_descriptor)
-	    );
-	usb_standard_configuration_descriptor_t descriptor;
-	memcpy(&descriptor, &ohci_rh_conf_descriptor,
-	    sizeof (ohci_rh_conf_descriptor));
-
-	int opResult = create_serialized_hub_descriptor(instance);
-	if (opResult != EOK) {
-		return opResult;
-	}
-	descriptor.total_length =
-	    sizeof (usb_standard_configuration_descriptor_t) +
-	    sizeof (usb_standard_endpoint_descriptor_t) +
-	    sizeof (usb_standard_interface_descriptor_t) +
-	    instance->descriptor_size;
-
-	uint8_t * full_config_descriptor =
-	    (uint8_t*) malloc(descriptor.total_length);
-	if (!full_config_descriptor) {
-		return ENOMEM;
-	}
-	memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor),
-	    &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor) +
-	    sizeof (ohci_rh_iface_descriptor),
-	    &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor) +
-	    sizeof (ohci_rh_iface_descriptor) +
-	    sizeof (ohci_rh_ep_descriptor),
-	    instance->hub_descriptor, instance->descriptor_size);
-
-	instance->descriptors.configuration = full_config_descriptor;
-	instance->descriptors.configuration_size = descriptor.total_length;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to port status_request
- *
- * Copy content of corresponding port status register to answer buffer. The
- * format of the port status register and port status data is the same (
- * see OHCI root hub and USB hub documentation).
- *
- * @param instance root hub instance
- * @param port port number, counted from 1
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_port_status_request(rh_t *instance, uint16_t port,
-    usb_transfer_batch_t * request) {
-	if (port < 1 || port > instance->port_count)
-		return EINVAL;
-	request->transfered_size = 4;
-	uint32_t data = instance->registers->rh_port_status[port - 1];
-	memcpy(request->data_buffer, &data, 4);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to port status_request
- *
- * This copies flags in hub status register into the buffer. The format of the
- * status register and status message is the same, according to USB hub
- * specification and OHCI root hub specification.
- *
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_hub_status_request(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	request->transfered_size = 4;
-	//bits, 0,1,16,17
-	uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
-	uint32_t data = mask & instance->registers->rh_status;
-	memcpy(request->data_buffer, &data, 4);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to status request
- *
- * This might be either hub status or port status request. If neither,
- * ENOTSUP is returned.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_status_request(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	size_t buffer_size = request->buffer_size;
-	usb_device_request_setup_packet_t * request_packet =
-	    (usb_device_request_setup_packet_t*)
-	    request->setup_buffer;
-
-	usb_hub_bm_request_type_t request_type = request_packet->request_type;
-	if (buffer_size < 4) {
-		usb_log_warning("Requested more data than buffer size\n");
-		return EINVAL;
-	}
-
-	if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
-		return process_get_hub_status_request(instance, request);
-	if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
-		return process_get_port_status_request(instance,
-	    request_packet->index,
-	    request);
-
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to status interrupt consisting of change bitmap
- *
- * Result contains bitmap where bit 0 indicates change on hub and
- * bit i indicates change on i`th port (i>0). For more info see
- * Hub and Port status bitmap specification in USB specification
- * (chapter 11.13.4).
- * Uses instance`s interrupt buffer to store the interrupt information.
- * @param instance root hub instance
- */
-static void create_interrupt_mask_in_instance(rh_t * instance) {
-	uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
-	uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
-	    | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
-	bzero(bitmap, instance->interrupt_mask_size);
-	if ((instance->registers->rh_status & mask) != 0) {
-		bitmap[0] = 1;
-	}
-	size_t port;
-	mask = port_status_change_mask;
-	for (port = 1; port <= instance->port_count; ++port) {
-		if ((mask & instance->registers->rh_port_status[port - 1]) != 0) {
-
-			bitmap[(port) / 8] += 1 << (port % 8);
-		}
-	}
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to a descriptor request
- *
- * This might be a request for standard (configuration, device, endpoint or
- * interface) or device specific (hub) descriptor.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_descriptor_request(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	size_t size;
-	const void * result_descriptor = NULL;
-	const uint16_t setup_request_value = setup_request->value_high;
-	//(setup_request->value_low << 8);
-	switch (setup_request_value) {
-		case USB_DESCTYPE_HUB:
-		{
-			usb_log_debug("USB_DESCTYPE_HUB\n");
-			result_descriptor = instance->hub_descriptor;
-			size = instance->descriptor_size;
-			break;
-		}
-		case USB_DESCTYPE_DEVICE:
-		{
-			usb_log_debug("USB_DESCTYPE_DEVICE\n");
-			result_descriptor = &ohci_rh_device_descriptor;
-			size = sizeof (ohci_rh_device_descriptor);
-			break;
-		}
-		case USB_DESCTYPE_CONFIGURATION:
-		{
-			usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
-			result_descriptor = instance->descriptors.configuration;
-			size = instance->descriptors.configuration_size;
-			break;
-		}
-		case USB_DESCTYPE_INTERFACE:
-		{
-			usb_log_debug("USB_DESCTYPE_INTERFACE\n");
-			result_descriptor = &ohci_rh_iface_descriptor;
-			size = sizeof (ohci_rh_iface_descriptor);
-			break;
-		}
-		case USB_DESCTYPE_ENDPOINT:
-		{
-			usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
-			result_descriptor = &ohci_rh_ep_descriptor;
-			size = sizeof (ohci_rh_ep_descriptor);
-			break;
-		}
-		default:
-		{
-			usb_log_debug("USB_DESCTYPE_EINVAL %d \n",
-			    setup_request->value);
-			usb_log_debug("\ttype %d\n\trequest %d\n\tvalue "
-			    "%d\n\tindex %d\n\tlen %d\n ",
-			    setup_request->request_type,
-			    setup_request->request,
-			    setup_request_value,
-			    setup_request->index,
-			    setup_request->length
-			    );
-			return EINVAL;
-		}
-	}
-	if (request->buffer_size < size) {
-		size = request->buffer_size;
-	}
-	request->transfered_size = size;
-	memcpy(request->data_buffer, result_descriptor, size);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * answer to get configuration request
- *
- * Root hub works independently on the configuration.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_configuration_request(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	//set and get configuration requests do not have any meaning, only dummy
-	//values are returned
-	if (request->buffer_size != 1)
-		return EINVAL;
-	request->data_buffer[0] = 1;
-	request->transfered_size = 1;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-enabling request on hub
- *
- * @param instance root hub instance
- * @param feature feature selector
- * @return error code
- */
-static int process_hub_feature_set_request(rh_t *instance,
-    uint16_t feature) {
-	if (!((1 << feature) & hub_set_feature_valid_mask))
-		return EINVAL;
-	if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
-		feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
-	instance->registers->rh_status =
-	    (instance->registers->rh_status | (1 << feature))
-	    & (~hub_clear_feature_by_writing_one_mask);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-disabling request on hub
- *
- * @param instance root hub instance
- * @param feature feature selector
- * @return error code
- */
-static int process_hub_feature_clear_request(rh_t *instance,
-    uint16_t feature) {
-	if (!((1 << feature) & hub_clear_feature_valid_mask))
-		return EINVAL;
-	//is the feature cleared directly?
-	if ((1 << feature) & hub_set_feature_direct_mask) {
-		instance->registers->rh_status =
-		    (instance->registers->rh_status & (~(1 << feature)))
-		    & (~hub_clear_feature_by_writing_one_mask);
-	} else {//the feature is cleared by writing '1'
-
-		instance->registers->rh_status =
-		    (instance->registers->rh_status
-		    & (~hub_clear_feature_by_writing_one_mask))
-		    | (1 << feature);
-	}
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-enabling request on hub
- *
- * @param instance root hub instance
- * @param feature feature selector
- * @param port port number, counted from 1
- * @param enable enable or disable the specified feature
- * @return error code
- */
-static int process_port_feature_set_request(rh_t *instance,
-    uint16_t feature, uint16_t port) {
-	if (!((1 << feature) & port_set_feature_valid_mask))
-		return EINVAL;
-	if (port < 1 || port > instance->port_count)
-		return EINVAL;
-	instance->registers->rh_port_status[port - 1] =
-	    (instance->registers->rh_port_status[port - 1] | (1 << feature))
-	    & (~port_clear_feature_valid_mask);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-disabling request on hub
- *
- * @param instance root hub instance
- * @param feature feature selector
- * @param port port number, counted from 1
- * @param enable enable or disable the specified feature
- * @return error code
- */
-static int process_port_feature_clear_request(rh_t *instance,
-    uint16_t feature, uint16_t port) {
-	if (!((1 << feature) & port_clear_feature_valid_mask))
-		return EINVAL;
-	if (port < 1 || port > instance->port_count)
-		return EINVAL;
-	if (feature == USB_HUB_FEATURE_PORT_POWER)
-		feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
-	if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
-		feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
-	instance->registers->rh_port_status[port - 1] =
-	    (instance->registers->rh_port_status[port - 1]
-	    & (~port_clear_feature_valid_mask))
-	    | (1 << feature);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * register address to this device
- *
- * @param instance root hub instance
- * @param address new address
- * @return error code
- */
-static int process_address_set_request(rh_t *instance,
-    uint16_t address) {
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process one of requests that requere output data
- *
- * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or
- * USB_DEVREQ_GET_CONFIGURATION.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_request_with_output(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	if (setup_request->request == USB_DEVREQ_GET_STATUS) {
-		usb_log_debug("USB_DEVREQ_GET_STATUS\n");
-		return process_get_status_request(instance, request);
-	}
-	if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
-		usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
-		return process_get_descriptor_request(instance, request);
-	}
-	if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
-		usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
-
-		return process_get_configuration_request(instance, request);
-	}
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process one of requests that carry input data
- *
- * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or
- * USB_DEVREQ_SET_CONFIGURATION.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_request_with_input(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	request->transfered_size = 0;
-	if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
-		return ENOTSUP;
-	}
-	if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
-		//set and get configuration requests do not have any meaning,
-		//only dummy values are returned
-
-		return EOK;
-	}
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process one of requests that do not request nor carry additional data
- *
- * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or
- * USB_DEVREQ_SET_ADDRESS.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_request_without_data(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	request->transfered_size = 0;
-	if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
-			return process_hub_feature_clear_request(instance,
-			    setup_request->value);
-		}
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-			return process_port_feature_clear_request(instance,
-			    setup_request->value,
-			    setup_request->index);
-		}
-		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
-		    setup_request->request_type);
-		return EINVAL;
-	}
-	if (setup_request->request == USB_DEVREQ_SET_FEATURE) {
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
-			return process_hub_feature_set_request(instance,
-			    setup_request->value);
-		}
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-			return process_port_feature_set_request(instance,
-			    setup_request->value,
-			    setup_request->index);
-		}
-		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
-		    setup_request->request_type);
-		return EINVAL;
-	}
-	if (setup_request->request == USB_DEVREQ_SET_ADDRESS) {
-		usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
-		return process_address_set_request(instance,
-		    setup_request->value);
-	}
-	usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
-	    setup_request->request_type);
-
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process hub control request
- *
- * If needed, writes answer into the request structure.
- * Request can be one of
- * USB_DEVREQ_GET_STATUS,
- * USB_DEVREQ_GET_DESCRIPTOR,
- * USB_DEVREQ_GET_CONFIGURATION,
- * USB_DEVREQ_CLEAR_FEATURE,
- * USB_DEVREQ_SET_FEATURE,
- * USB_DEVREQ_SET_ADDRESS,
- * USB_DEVREQ_SET_DESCRIPTOR or
- * USB_DEVREQ_SET_CONFIGURATION.
- *
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
-	if (!request->setup_buffer) {
-		usb_log_error("root hub received empty transaction?");
-		return EINVAL;
-	}
-	int opResult;
-	if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
-		usb_log_error("Setup packet too small\n");
-		return EINVAL;
-	}
-	usb_log_info("CTRL packet: %s.\n",
-	    usb_debug_str_buffer(
-	    (const uint8_t *) request->setup_buffer, 8, 8));
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*)
-	    request->setup_buffer;
-	switch (setup_request->request) {
-		case USB_DEVREQ_GET_STATUS:
-		case USB_DEVREQ_GET_DESCRIPTOR:
-		case USB_DEVREQ_GET_CONFIGURATION:
-			usb_log_debug("Processing request with output\n");
-			opResult = process_request_with_output(
-			    instance, request);
-			break;
-		case USB_DEVREQ_CLEAR_FEATURE:
-		case USB_DEVREQ_SET_FEATURE:
-		case USB_DEVREQ_SET_ADDRESS:
-			usb_log_debug("Processing request without "
-			    "additional data\n");
-			opResult = process_request_without_data(
-			    instance, request);
-			break;
-		case USB_DEVREQ_SET_DESCRIPTOR:
-		case USB_DEVREQ_SET_CONFIGURATION:
-			usb_log_debug("Processing request with "
-			    "input\n");
-			opResult = process_request_with_input(
-			    instance, request);
-
-			break;
-		default:
-			usb_log_warning("Received unsuported request: "
-			    "%d\n",
-			    setup_request->request
-			    );
-			opResult = ENOTSUP;
-	}
-	return opResult;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process hanging interrupt request
- *
- * If an interrupt transfer has been received and there was no change,
- * the driver stores the transfer information and waits for change to occcur.
- * This routine is called when that happens and it finalizes the interrupt
- * transfer.
- *
- * @param instance hub instance
- * @param request batch request to be processed
- *
- * @return
- */
-static int process_interrupt_mask_in_instance(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	memcpy(request->data_buffer, instance->interrupt_buffer,
-	    instance->interrupt_mask_size);
-	request->transfered_size = instance->interrupt_mask_size;
-	instance->unfinished_interrupt_transfer = NULL;
-	usb_transfer_batch_finish_error(request, EOK);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * return whether the buffer is full of zeros
- *
- * Convenience function.
- * @param buffer
- * @param size
- * @return
- */
-static bool is_zeros(void *buffer, size_t size) {
-	if (!buffer) return true;
-	if (!size) return true;
-	size_t i;
-	for (i = 0; i < size; ++i) {
-		if (((char*) buffer)[i])
-			return false;
-	}
-	return true;
-}
-
-/**
- * @}
- */
Index: pace/drv/ohci/root_hub.h
===================================================================
--- uspace/drv/ohci/root_hub.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,82 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#ifndef DRV_OHCI_ROOT_HUB_H
-#define DRV_OHCI_ROOT_HUB_H
-
-#include <usb/usb.h>
-#include <usb/dev/driver.h>
-
-#include "ohci_regs.h"
-#include "batch.h"
-
-/**
- * ohci root hub representation
- */
-typedef struct rh {
-	/** pointer to ohci driver registers */
-	ohci_regs_t *registers;
-	/** usb address of the root hub */
-	usb_address_t address;
-	/** hub port count */
-	size_t port_count;
-	/** hubs descriptors */
-	usb_device_descriptors_t descriptors;
-	/** interrupt transfer waiting for an actual interrupt to occur */
-	usb_transfer_batch_t * unfinished_interrupt_transfer;
-	/** pre-allocated interrupt mask
-	 *
-	 * This is allocated when initializing instance, so that memory
-	 * allocation is not needed when processing request. Buffer is used for
-	 * interrupt bitmask.
-	 */
-	uint8_t * interrupt_buffer;
-	/** size of interrupt buffer */
-	size_t interrupt_mask_size;
-	/** instance`s descriptor*/
-	uint8_t * hub_descriptor;
-	/** size of hub descriptor */
-	size_t descriptor_size;
-
-
-} rh_t;
-
-int rh_init(rh_t *instance, ohci_regs_t *regs);
-
-int rh_request(rh_t *instance, usb_transfer_batch_t *request);
-
-void rh_interrupt(rh_t *instance);
-#endif
-/**
- * @}
- */
Index: pace/drv/ohci/utils/malloc32.h
===================================================================
--- uspace/drv/ohci/utils/malloc32.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,75 +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 drvusbohci
- * @{
- */
-/** @file
- * @brief OHCI driver
- */
-#ifndef DRV_OHCI_UTILS_MALLOC32_H
-#define DRV_OHCI_UTILS_MALLOC32_H
-
-#include <assert.h>
-#include <malloc.h>
-#include <errno.h>
-#include <mem.h>
-#include <as.h>
-
-/** Get physical address translation
- *
- * @param[in] addr Virtual address to translate
- * @return Physical address if exists, NULL otherwise.
- */
-static inline uintptr_t addr_to_phys(void *addr)
-{
-	uintptr_t result;
-	int ret = as_get_physical_mapping(addr, &result);
-
-	if (ret != EOK)
-		return 0;
-	return (result | ((uintptr_t)addr & 0xfff));
-}
-/*----------------------------------------------------------------------------*/
-/** Physical mallocator simulator
- *
- * @param[in] size Size of the required memory space
- * @return Address of the aligned and big enough memory place, NULL on failure.
- */
-static inline void * malloc32(size_t size)
-	{ return memalign(size, size); }
-/*----------------------------------------------------------------------------*/
-/** Physical mallocator simulator
- *
- * @param[in] addr Address of the place allocated by malloc32
- */
-static inline void free32(void *addr)
-	{ if (addr) free(addr); }
-#endif
-/**
- * @}
- */
Index: pace/drv/pciintel/Makefile
===================================================================
--- uspace/drv/pciintel/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Lenka Trochtova
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = pciintel
-
-SOURCES = \
-	pci.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,759 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
- * 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.
- */
-
-/**
- * @defgroup pciintel pci bus driver for intel method 1.
- * @brief HelenOS root pci bus driver for intel method 1.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <str.h>
-#include <ctype.h>
-#include <macros.h>
-#include <str_error.h>
-
-#include <ddf/driver.h>
-#include <ddf/log.h>
-#include <devman.h>
-#include <ipc/devman.h>
-#include <ipc/dev_iface.h>
-#include <ipc/irc.h>
-#include <ns.h>
-#include <ipc/services.h>
-#include <sysinfo.h>
-#include <ops/hw_res.h>
-#include <device/hw_res.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-#include <pci_dev_iface.h>
-
-#include "pci.h"
-
-#define NAME "pciintel"
-
-#define CONF_ADDR(bus, dev, fn, reg) \
-	((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
-
-/** Obtain PCI function soft-state from DDF function node */
-#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
-
-/** Obtain PCI bus soft-state from DDF device node */
-#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
-
-/** Obtain PCI bus soft-state from function soft-state */
-#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
-
-static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
-{
-	pci_fun_t *fun = PCI_FUN(fnode);
-	
-	if (fun == NULL)
-		return NULL;
-	return &fun->hw_resources;
-}
-
-static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
-{
-	/* This is an old ugly way, copied from ne2000 driver */
-	assert(fnode);
-	pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
-	
-	sysarg_t apic;
-	sysarg_t i8259;
-	
-	async_sess_t *irc_sess = NULL;
-	
-	if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
-	    || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
-		irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
-		    SERVICE_IRC, 0, 0);
-	}
-	
-	if (!irc_sess)
-		return false;
-	
-	size_t i = 0;
-	hw_resource_list_t *res = &dev_data->hw_resources;
-	for (; i < res->count; i++) {
-		if (res->resources[i].type == INTERRUPT) {
-			const int irq = res->resources[i].res.interrupt.irq;
-			
-			async_exch_t *exch = async_exchange_begin(irc_sess);
-			const int rc =
-			    async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
-			async_exchange_end(exch);
-			
-			if (rc != EOK) {
-				async_hangup(irc_sess);
-				return false;
-			}
-		}
-	}
-	
-	async_hangup(irc_sess);
-	return true;
-}
-
-static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address,
-    uint32_t data)
-{
-	if (address > 252)
-		return EINVAL;
-	pci_conf_write_32(PCI_FUN(fun), address, data);
-	return EOK;
-}
-
-static int pci_config_space_write_16(
-    ddf_fun_t *fun, uint32_t address, uint16_t data)
-{
-	if (address > 254)
-		return EINVAL;
-	pci_conf_write_16(PCI_FUN(fun), address, data);
-	return EOK;
-}
-
-static int pci_config_space_write_8(
-    ddf_fun_t *fun, uint32_t address, uint8_t data)
-{
-	if (address > 255)
-		return EINVAL;
-	pci_conf_write_8(PCI_FUN(fun), address, data);
-	return EOK;
-}
-
-static int pci_config_space_read_32(
-    ddf_fun_t *fun, uint32_t address, uint32_t *data)
-{
-	if (address > 252)
-		return EINVAL;
-	*data = pci_conf_read_32(PCI_FUN(fun), address);
-	return EOK;
-}
-
-static int pci_config_space_read_16(
-    ddf_fun_t *fun, uint32_t address, uint16_t *data)
-{
-	if (address > 254)
-		return EINVAL;
-	*data = pci_conf_read_16(PCI_FUN(fun), address);
-	return EOK;
-}
-
-static int pci_config_space_read_8(
-    ddf_fun_t *fun, uint32_t address, uint8_t *data)
-{
-	if (address > 255)
-		return EINVAL;
-	*data = pci_conf_read_8(PCI_FUN(fun), address);
-	return EOK;
-}
-
-static hw_res_ops_t pciintel_hw_res_ops = {
-	&pciintel_get_resources,
-	&pciintel_enable_interrupt
-};
-
-static pci_dev_iface_t pci_dev_ops = {
-	.config_space_read_8 = &pci_config_space_read_8,
-	.config_space_read_16 = &pci_config_space_read_16,
-	.config_space_read_32 = &pci_config_space_read_32,
-	.config_space_write_8 = &pci_config_space_write_8,
-	.config_space_write_16 = &pci_config_space_write_16,
-	.config_space_write_32 = &pci_config_space_write_32
-};
-
-static ddf_dev_ops_t pci_fun_ops = {
-	.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
-	.interfaces[PCI_DEV_IFACE] = &pci_dev_ops
-};
-
-static int pci_add_device(ddf_dev_t *);
-
-/** PCI bus driver standard operations */
-static driver_ops_t pci_ops = {
-	.add_device = &pci_add_device
-};
-
-/** PCI bus driver structure */
-static driver_t pci_driver = {
-	.name = NAME,
-	.driver_ops = &pci_ops
-};
-
-static pci_bus_t *pci_bus_new(void)
-{
-	pci_bus_t *bus;
-	
-	bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));
-	if (bus == NULL)
-		return NULL;
-	
-	fibril_mutex_initialize(&bus->conf_mutex);
-	return bus;
-}
-
-static void pci_bus_delete(pci_bus_t *bus)
-{
-	assert(bus != NULL);
-	free(bus);
-}
-
-static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
-{
-	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
-	
-	fibril_mutex_lock(&bus->conf_mutex);
-	
-	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
-	void *addr = bus->conf_data_port + (reg & 3);
-	
-	pio_write_32(bus->conf_addr_port, conf_addr);
-	
-	switch (len) {
-	case 1:
-		buf[0] = pio_read_8(addr);
-		break;
-	case 2:
-		((uint16_t *) buf)[0] = pio_read_16(addr);
-		break;
-	case 4:
-		((uint32_t *) buf)[0] = pio_read_32(addr);
-		break;
-	}
-	
-	fibril_mutex_unlock(&bus->conf_mutex);
-}
-
-static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
-{
-	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
-	
-	fibril_mutex_lock(&bus->conf_mutex);
-	
-	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
-	void *addr = bus->conf_data_port + (reg & 3);
-	
-	pio_write_32(bus->conf_addr_port, conf_addr);
-	
-	switch (len) {
-	case 1:
-		pio_write_8(addr, buf[0]);
-		break;
-	case 2:
-		pio_write_16(addr, ((uint16_t *) buf)[0]);
-		break;
-	case 4:
-		pio_write_32(addr, ((uint32_t *) buf)[0]);
-		break;
-	}
-	
-	fibril_mutex_unlock(&bus->conf_mutex);
-}
-
-uint8_t pci_conf_read_8(pci_fun_t *fun, int reg)
-{
-	uint8_t res;
-	pci_conf_read(fun, reg, &res, 1);
-	return res;
-}
-
-uint16_t pci_conf_read_16(pci_fun_t *fun, int reg)
-{
-	uint16_t res;
-	pci_conf_read(fun, reg, (uint8_t *) &res, 2);
-	return res;
-}
-
-uint32_t pci_conf_read_32(pci_fun_t *fun, int reg)
-{
-	uint32_t res;
-	pci_conf_read(fun, reg, (uint8_t *) &res, 4);
-	return res;
-}
-
-void pci_conf_write_8(pci_fun_t *fun, int reg, uint8_t val)
-{
-	pci_conf_write(fun, reg, (uint8_t *) &val, 1);
-}
-
-void pci_conf_write_16(pci_fun_t *fun, int reg, uint16_t val)
-{
-	pci_conf_write(fun, reg, (uint8_t *) &val, 2);
-}
-
-void pci_conf_write_32(pci_fun_t *fun, int reg, uint32_t val)
-{
-	pci_conf_write(fun, reg, (uint8_t *) &val, 4);
-}
-
-void pci_fun_create_match_ids(pci_fun_t *fun)
-{
-	char *match_id_str;
-	int rc;
-	
-	asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
-	    fun->vendor_id, fun->device_id);
-
-	if (match_id_str == NULL) {
-		ddf_msg(LVL_ERROR, "Out of memory creating match ID.");
-		return;
-	}
-
-	rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
-		    str_error(rc));
-	}
-	
-	/* TODO add more ids (with subsys ids, using class id etc.) */
-}
-
-void pci_add_range(pci_fun_t *fun, uint64_t range_addr, size_t range_size,
-    bool io)
-{
-	hw_resource_list_t *hw_res_list = &fun->hw_resources;
-	hw_resource_t *hw_resources =  hw_res_list->resources;
-	size_t count = hw_res_list->count;
-	
-	assert(hw_resources != NULL);
-	assert(count < PCI_MAX_HW_RES);
-	
-	if (io) {
-		hw_resources[count].type = IO_RANGE;
-		hw_resources[count].res.io_range.address = range_addr;
-		hw_resources[count].res.io_range.size = range_size;
-		hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
-	} else {
-		hw_resources[count].type = MEM_RANGE;
-		hw_resources[count].res.mem_range.address = range_addr;
-		hw_resources[count].res.mem_range.size = range_size;
-		hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
-	}
-	
-	hw_res_list->count++;
-}
-
-/** Read the base address register (BAR) of the device and if it contains valid
- * address add it to the devices hw resource list.
- *
- * @param fun	PCI function
- * @param addr	The address of the BAR in the PCI configuration address space of
- *		the device
- * @return	The addr the address of the BAR which should be read next
- */
-int pci_read_bar(pci_fun_t *fun, int addr)
-{
-	/* Value of the BAR */
-	uint32_t val, mask;
-	/* IO space address */
-	bool io;
-	/* 64-bit wide address */
-	bool addrw64;
-	
-	/* Size of the io or memory range specified by the BAR */
-	size_t range_size;
-	/* Beginning of the io or memory range specified by the BAR */
-	uint64_t range_addr;
-	
-	/* Get the value of the BAR. */
-	val = pci_conf_read_32(fun, addr);
-
-#define IO_MASK  (~0x3)
-#define MEM_MASK (~0xf)
-	
-	io = (bool) (val & 1);
-	if (io) {
-		addrw64 = false;
-		mask = IO_MASK;
-	} else {
-		mask = MEM_MASK;
-		switch ((val >> 1) & 3) {
-		case 0:
-			addrw64 = false;
-			break;
-		case 2:
-			addrw64 = true;
-			break;
-		default:
-			/* reserved, go to the next BAR */
-			return addr + 4;
-		}
-	}
-	
-	/* Get the address mask. */
-	pci_conf_write_32(fun, addr, 0xffffffff);
-	mask &= pci_conf_read_32(fun, addr);
-	
-	/* Restore the original value. */
-	pci_conf_write_32(fun, addr, val);
-	val = pci_conf_read_32(fun, addr);
-	
-	range_size = pci_bar_mask_to_size(mask);
-	
-	if (addrw64) {
-		range_addr = ((uint64_t)pci_conf_read_32(fun, addr + 4) << 32) |
-		    (val & 0xfffffff0);
-	} else {
-		range_addr = (val & 0xfffffff0);
-	}
-	
-	if (range_addr != 0) {
-		ddf_msg(LVL_DEBUG, "Function %s : address = %" PRIx64
-		    ", size = %x", fun->fnode->name, range_addr,
-		    (unsigned int) range_size);
-	}
-	
-	pci_add_range(fun, range_addr, range_size, io);
-	
-	if (addrw64)
-		return addr + 8;
-	
-	return addr + 4;
-}
-
-void pci_add_interrupt(pci_fun_t *fun, int irq)
-{
-	hw_resource_list_t *hw_res_list = &fun->hw_resources;
-	hw_resource_t *hw_resources = hw_res_list->resources;
-	size_t count = hw_res_list->count;
-	
-	assert(NULL != hw_resources);
-	assert(count < PCI_MAX_HW_RES);
-	
-	hw_resources[count].type = INTERRUPT;
-	hw_resources[count].res.interrupt.irq = irq;
-	
-	hw_res_list->count++;
-	
-	ddf_msg(LVL_NOTE, "Function %s uses irq %x.", fun->fnode->name, irq);
-}
-
-void pci_read_interrupt(pci_fun_t *fun)
-{
-	uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
-	if (irq != 0xff)
-		pci_add_interrupt(fun, irq);
-}
-
-/** Enumerate (recursively) and register the devices connected to a pci bus.
- *
- * @param bus		Host-to-PCI bridge
- * @param bus_num	Bus number
- */
-void pci_bus_scan(pci_bus_t *bus, int bus_num) 
-{
-	ddf_fun_t *fnode;
-	pci_fun_t *fun;
-	
-	int child_bus = 0;
-	int dnum, fnum;
-	bool multi;
-	uint8_t header_type;
-	
-	fun = pci_fun_new(bus);
-	
-	for (dnum = 0; dnum < 32; dnum++) {
-		multi = true;
-		for (fnum = 0; multi && fnum < 8; fnum++) {
-			pci_fun_init(fun, bus_num, dnum, fnum);
-			fun->vendor_id = pci_conf_read_16(fun,
-			    PCI_VENDOR_ID);
-			fun->device_id = pci_conf_read_16(fun,
-			    PCI_DEVICE_ID);
-			if (fun->vendor_id == 0xffff) {
-				/*
-				 * The device is not present, go on scanning the
-				 * bus.
-				 */
-				if (fnum == 0)
-					break;
-				else
-					continue;
-			}
-			
-			header_type = pci_conf_read_8(fun, PCI_HEADER_TYPE);
-			if (fnum == 0) {
-				/* Is the device multifunction? */
-				multi = header_type >> 7;
-			}
-			/* Clear the multifunction bit. */
-			header_type = header_type & 0x7F;
-			
-			char *fun_name = pci_fun_create_name(fun);
-			if (fun_name == NULL) {
-				ddf_msg(LVL_ERROR, "Out of memory.");
-				return;
-			}
-			
-			fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
-			if (fnode == NULL) {
-				ddf_msg(LVL_ERROR, "Failed creating function.");
-				return;
-			}
-			
-			free(fun_name);
-			fun->fnode = fnode;
-			
-			pci_alloc_resource_list(fun);
-			pci_read_bars(fun);
-			pci_read_interrupt(fun);
-			
-			fnode->ops = &pci_fun_ops;
-			fnode->driver_data = fun;
-			
-			ddf_msg(LVL_DEBUG, "Adding new function %s.",
-			    fnode->name);
-			
-			pci_fun_create_match_ids(fun);
-			
-			if (ddf_fun_bind(fnode) != EOK) {
-				pci_clean_resource_list(fun);
-				clean_match_ids(&fnode->match_ids);
-				free((char *) fnode->name);
-				fnode->name = NULL;
-				continue;
-			}
-			
-			if (header_type == PCI_HEADER_TYPE_BRIDGE ||
-			    header_type == PCI_HEADER_TYPE_CARDBUS) {
-				child_bus = pci_conf_read_8(fun,
-				    PCI_BRIDGE_SEC_BUS_NUM);
-				ddf_msg(LVL_DEBUG, "Device is pci-to-pci "
-				    "bridge, secondary bus number = %d.",
-				    bus_num);
-				if (child_bus > bus_num)
-					pci_bus_scan(bus, child_bus);
-			}
-			
-			fun = pci_fun_new(bus);
-		}
-	}
-	
-	if (fun->vendor_id == 0xffff) {
-		/* Free the auxiliary function structure. */
-		pci_fun_delete(fun);
-	}
-}
-
-static int pci_add_device(ddf_dev_t *dnode)
-{
-	pci_bus_t *bus = NULL;
-	ddf_fun_t *ctl = NULL;
-	bool got_res = false;
-	int rc;
-	
-	ddf_msg(LVL_DEBUG, "pci_add_device");
-	dnode->parent_sess = NULL;
-	
-	bus = pci_bus_new();
-	if (bus == NULL) {
-		ddf_msg(LVL_ERROR, "pci_add_device allocation failed.");
-		rc = ENOMEM;
-		goto fail;
-	}
-	bus->dnode = dnode;
-	dnode->driver_data = bus;
-	
-	dnode->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
-	    dnode->handle, IPC_FLAG_BLOCKING);
-	if (!dnode->parent_sess) {
-		ddf_msg(LVL_ERROR, "pci_add_device failed to connect to the "
-		    "parent driver.");
-		rc = ENOENT;
-		goto fail;
-	}
-	
-	hw_resource_list_t hw_resources;
-	
-	rc = hw_res_get_resource_list(dnode->parent_sess, &hw_resources);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "pci_add_device failed to get hw resources "
-		    "for the device.");
-		goto fail;
-	}
-	got_res = true;
-	
-	ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".",
-	    hw_resources.resources[0].res.io_range.address);
-	
-	assert(hw_resources.count > 0);
-	assert(hw_resources.resources[0].type == IO_RANGE);
-	assert(hw_resources.resources[0].res.io_range.size == 8);
-	
-	bus->conf_io_addr =
-	    (uint32_t) hw_resources.resources[0].res.io_range.address;
-	
-	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
-	    &bus->conf_addr_port)) {
-		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
-		rc = EADDRNOTAVAIL;
-		goto fail;
-	}
-	bus->conf_data_port = (char *) bus->conf_addr_port + 4;
-	
-	/* Make the bus device more visible. It has no use yet. */
-	ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
-	
-	ctl = ddf_fun_create(bus->dnode, fun_exposed, "ctl");
-	if (ctl == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating control function.");
-		rc = ENOMEM;
-		goto fail;
-	}
-	
-	rc = ddf_fun_bind(ctl);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding control function.");
-		goto fail;
-	}
-	
-	/* Enumerate functions. */
-	ddf_msg(LVL_DEBUG, "Scanning the bus");
-	pci_bus_scan(bus, 0);
-	
-	hw_res_clean_resource_list(&hw_resources);
-	
-	return EOK;
-	
-fail:
-	if (bus != NULL)
-		pci_bus_delete(bus);
-	
-	if (dnode->parent_sess)
-		async_hangup(dnode->parent_sess);
-	
-	if (got_res)
-		hw_res_clean_resource_list(&hw_resources);
-	
-	if (ctl != NULL)
-		ddf_fun_destroy(ctl);
-	
-	return rc;
-}
-
-static void pciintel_init(void)
-{
-	ddf_log_init(NAME, LVL_ERROR);
-	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
-	pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
-}
-
-pci_fun_t *pci_fun_new(pci_bus_t *bus)
-{
-	pci_fun_t *fun;
-	
-	fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
-	if (fun == NULL)
-		return NULL;
-
-	fun->busptr = bus;
-	return fun;
-}
-
-void pci_fun_init(pci_fun_t *fun, int bus, int dev, int fn)
-{
-	fun->bus = bus;
-	fun->dev = dev;
-	fun->fn = fn;
-}
-
-void pci_fun_delete(pci_fun_t *fun)
-{
-	assert(fun != NULL);
-	hw_res_clean_resource_list(&fun->hw_resources);
-	free(fun);
-}
-
-char *pci_fun_create_name(pci_fun_t *fun)
-{
-	char *name = NULL;
-	
-	asprintf(&name, "%02x:%02x.%01x", fun->bus, fun->dev,
-	    fun->fn);
-	return name;
-}
-
-bool pci_alloc_resource_list(pci_fun_t *fun)
-{
-	fun->hw_resources.resources =
-	    (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
-	return fun->hw_resources.resources != NULL;
-}
-
-void pci_clean_resource_list(pci_fun_t *fun)
-{
-	if (fun->hw_resources.resources != NULL) {
-		free(fun->hw_resources.resources);
-		fun->hw_resources.resources = NULL;
-	}
-}
-
-/** Read the base address registers (BARs) of the function and add the addresses
- * to its HW resource list.
- *
- * @param fun	PCI function
- */
-void pci_read_bars(pci_fun_t *fun)
-{
-	/*
-	 * Position of the BAR in the PCI configuration address space of the
-	 * device.
-	 */
-	int addr = PCI_BASE_ADDR_0;
-	
-	while (addr <= PCI_BASE_ADDR_5)
-		addr = pci_read_bar(fun, addr);
-}
-
-size_t pci_bar_mask_to_size(uint32_t mask)
-{
-	size_t size = mask & ~(mask - 1);
-	return size;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS PCI bus driver (Intel method 1).\n");
-	pciintel_init();
-	return ddf_driver_main(&pci_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/pciintel/pci.h
===================================================================
--- uspace/drv/pciintel/pci.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,96 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
- * 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 pciintel
- * @{
- */
-/** @file
- */
-
-#ifndef PCI_H_
-#define PCI_H_
-
-#include <ddf/driver.h>
-#include "pci_regs.h"
-
-#define PCI_MAX_HW_RES 8
-
-typedef struct pciintel_bus {
-	/** DDF device node */
-	ddf_dev_t *dnode;
-	uint32_t conf_io_addr;
-	void *conf_data_port;
-	void *conf_addr_port;
-	fibril_mutex_t conf_mutex;
-} pci_bus_t;
-
-typedef struct pci_fun_data {
-	pci_bus_t *busptr;
-	ddf_fun_t *fnode;
-
-	int bus;
-	int dev;
-	int fn;
-	int vendor_id;
-	int device_id;
-	hw_resource_list_t hw_resources;
-} pci_fun_t;
-
-extern void pci_fun_create_match_ids(pci_fun_t *);
-
-extern uint8_t pci_conf_read_8(pci_fun_t *, int);
-extern uint16_t pci_conf_read_16(pci_fun_t *, int);
-extern uint32_t pci_conf_read_32(pci_fun_t *, int);
-extern void pci_conf_write_8(pci_fun_t *, int, uint8_t);
-extern void pci_conf_write_16(pci_fun_t *, int, uint16_t);
-extern void pci_conf_write_32(pci_fun_t *, int, uint32_t);
-
-extern void pci_add_range(pci_fun_t *, uint64_t, size_t, bool);
-extern int pci_read_bar(pci_fun_t *, int);
-extern void pci_read_interrupt(pci_fun_t *);
-extern void pci_add_interrupt(pci_fun_t *, int);
-
-extern pci_fun_t *pci_fun_new(pci_bus_t *);
-extern void pci_fun_init(pci_fun_t *, int, int, int);
-extern void pci_fun_delete(pci_fun_t *);
-extern char *pci_fun_create_name(pci_fun_t *);
-
-extern void pci_bus_scan(pci_bus_t *, int);
-
-extern bool pci_alloc_resource_list(pci_fun_t *);
-extern void pci_clean_resource_list(pci_fun_t *);
-
-extern void pci_read_bars(pci_fun_t *);
-extern size_t pci_bar_mask_to_size(uint32_t);
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/pciintel/pci_regs.h
===================================================================
--- uspace/drv/pciintel/pci_regs.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,101 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * 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 pciintel
- * @{
- */
-/** @file
- */
-
-#ifndef PCI_REGS_H_
-#define PCI_REGS_H_
-
-/* Header types */
-#define PCI_HEADER_TYPE_DEV	0
-#define PCI_HEADER_TYPE_BRIDGE	1
-#define PCI_HEADER_TYPE_CARDBUS	2
-
-/* Header type 0 and 1 */
-#define PCI_VENDOR_ID		0x00
-#define PCI_DEVICE_ID		0x02
-#define PCI_COMMAND		0x04
-#define PCI_STATUS		0x06
-#define PCI_REVISION_ID		0x08
-#define PCI_PROG_IF		0x09
-#define PCI_SUB_CLASS		0x0A
-#define PCI_BASE_CLASS		0x0B
-#define PCI_CACHE_LINE_SIZE	0x0C
-#define PCI_LATENCY_TIMER	0x0D
-#define PCI_HEADER_TYPE		0x0E
-#define PCI_BIST		0x0F
-
-#define PCI_BASE_ADDR_0		0x10
-#define PCI_BASE_ADDR_1		0x14
-
-/* Header type 0 */
-#define PCI_BASE_ADDR_2			0x18
-#define PCI_BASE_ADDR_3			0x1B
-#define PCI_BASE_ADDR_4			0x20
-#define PCI_BASE_ADDR_5			0x24
-
-#define PCI_CARDBUS_CIS_PTR		0x28
-#define PCI_SUBSYSTEM_VENDOR_ID		0x2C
-#define PCI_SUBSYSTEM_ID		0x2E
-#define PCI_EXP_ROM_BASE		0x30
-#define PCI_CAP_PTR			0x34
-#define PCI_INT_LINE			0x3C
-#define PCI_INT_PIN			0x3D
-#define PCI_MIN_GNT			0x3E
-#define PCI_MAX_LAT			0x3F
-
-/* Header type 1 */
-#define PCI_BRIDGE_PRIM_BUS_NUM		0x18
-#define PCI_BRIDGE_SEC_BUS_NUM		0x19
-#define PCI_BRIDGE_SUBORD_BUS_NUM	0x1A
-#define PCI_BRIDGE_SEC_LATENCY_TIMER	0x1B
-#define PCI_BRIDGE_IO_BASE		0x1C
-#define PCI_BRIDGE_IO_LIMIT		0x1D
-#define PCI_BRIDGE_SEC_STATUS		0x1E
-#define PCI_BRIDGE_MEMORY_BASE		0x20
-#define PCI_BRIDGE_MEMORY_LIMIT		0x22
-#define PCI_BRIDGE_PREF_MEMORY_BASE	0x24
-#define PCI_BRIDGE_PREF_MEMORY_LIMIT	0x26
-#define PCI_BRIDGE_PREF_MEMORY_BASE_UP	0x28
-#define PCI_BRIDGE_PREF_MEMORY_LIMIT_UP	0x2C
-#define PCI_BRIDGE_IO_BASE_UP		0x30
-#define PCI_BRIDGE_IO_LIMIT_UP		0x32
-#define PCI_BRIDGE_EXP_ROM_BASE		0x38
-#define PCI_BRIDGE_INT_LINE		0x3C
-#define PCI_BRIDGE_INT_PIN		0x3D
-#define PCI_BRIDGE_CTL			0x3E
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/pciintel/pciintel.ma
===================================================================
--- uspace/drv/pciintel/pciintel.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 intel_pci
Index: pace/drv/root/Makefile
===================================================================
--- uspace/drv/root/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Lenka Trochtova
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = root
-
-SOURCES = \
-	root.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/root/root.c
===================================================================
--- uspace/drv/root/root.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,225 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2010 Vojtech Horky
- * Copyright (c) 2011 Jiri Svoboda
- * 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.
- */
-
-/**
- * @defgroup root Root device driver.
- * @brief HelenOS root device driver.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <str_error.h>
-#include <ctype.h>
-#include <macros.h>
-#include <inttypes.h>
-#include <sysinfo.h>
-
-#include <ddf/driver.h>
-#include <ddf/log.h>
-#include <devman.h>
-#include <ipc/devman.h>
-
-#define NAME "root"
-
-#define PLATFORM_FUN_NAME "hw"
-#define PLATFORM_FUN_MATCH_ID_FMT "platform/%s"
-#define PLATFORM_FUN_MATCH_SCORE 100
-
-#define VIRTUAL_FUN_NAME "virt"
-#define VIRTUAL_FUN_MATCH_ID "rootvirt"
-#define VIRTUAL_FUN_MATCH_SCORE 100
-
-static int root_add_device(ddf_dev_t *dev);
-
-/** The root device driver's standard operations. */
-static driver_ops_t root_ops = {
-	.add_device = &root_add_device
-};
-
-/** The root device driver structure. */
-static driver_t root_driver = {
-	.name = NAME,
-	.driver_ops = &root_ops
-};
-
-/** Create the function which represents the root of virtual device tree.
- *
- * @param dev	Device
- * @return	EOK on success or negative error code
- */
-static int add_virtual_root_fun(ddf_dev_t *dev)
-{
-	const char *name = VIRTUAL_FUN_NAME;
-	ddf_fun_t *fun;
-	int rc;
-
-	ddf_msg(LVL_DEBUG, "Adding new function for virtual devices. "
-	    "Function node is `%s' (%d %s)", name,
-	    VIRTUAL_FUN_MATCH_SCORE, VIRTUAL_FUN_MATCH_ID);
-
-	fun = ddf_fun_create(dev, fun_inner, name);
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, VIRTUAL_FUN_MATCH_ID,
-	    VIRTUAL_FUN_MATCH_SCORE);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
-		    name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Create the function which represents the root of HW device tree.
- *
- * @param dev	Device
- * @return	EOK on success or negative error code
- */
-static int add_platform_fun(ddf_dev_t *dev)
-{
-	char *match_id;
-	char *platform;
-	size_t platform_size;
-
-	const char *name = PLATFORM_FUN_NAME;
-	ddf_fun_t *fun;
-	int rc;
-
-	/* Get platform name from sysinfo. */
-	platform = sysinfo_get_data("platform", &platform_size);
-	if (platform == NULL) {
-		ddf_msg(LVL_ERROR, "Failed to obtain platform name.");
-		return ENOENT;
-	}
-
-	/* Null-terminate string. */
-	platform = realloc(platform, platform_size + 1);
-	if (platform == NULL) {
-		ddf_msg(LVL_ERROR, "Memory allocation failed.");
-		return ENOMEM;
-	}
-
-	platform[platform_size] = '\0';
-
-	/* Construct match ID. */
-	if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
-		ddf_msg(LVL_ERROR, "Memory allocation failed.");
-		return ENOMEM;
-	}
-
-	/* Add function. */
-	ddf_msg(LVL_DEBUG, "Adding platform function. Function node is `%s' "
-	    " (%d %s)", PLATFORM_FUN_NAME, PLATFORM_FUN_MATCH_SCORE,
-	    match_id);
-
-	fun = ddf_fun_create(dev, fun_inner, name);
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Error creating function %s", name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, match_id, PLATFORM_FUN_MATCH_SCORE);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
-		    name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Get the root device.
- *
- * @param dev		The device which is root of the whole device tree (both
- *			of HW and pseudo devices).
- */
-static int root_add_device(ddf_dev_t *dev)
-{
-	ddf_msg(LVL_DEBUG, "root_add_device, device handle=%" PRIun,
-	    dev->handle);
-
-	/*
-	 * Register virtual devices root.
-	 * We ignore error occurrence because virtual devices shall not be
-	 * vital for the system.
-	 */
-	add_virtual_root_fun(dev);
-
-	/* Register root device's children. */
-	int res = add_platform_fun(dev);
-	if (EOK != res)
-		ddf_msg(LVL_ERROR, "Failed adding child device for platform.");
-
-	return res;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS root device driver\n");
-
-	ddf_log_init(NAME, LVL_ERROR);
-	return ddf_driver_main(&root_driver);
-}
-
-/**
- * @}
- */
-
Index: pace/drv/root/root.ma
===================================================================
--- uspace/drv/root/root.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 root
Index: pace/drv/rootpc/Makefile
===================================================================
--- uspace/drv/rootpc/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Lenka Trochtova
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = rootpc
-
-SOURCES = \
-	rootpc.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/rootpc/rootpc.c
===================================================================
--- uspace/drv/rootpc/rootpc.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,205 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * 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.
- */
-
-/**
- * @defgroup root_pc PC platform driver.
- * @brief HelenOS PC platform driver.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <ctype.h>
-#include <macros.h>
-
-#include <ddf/driver.h>
-#include <ddf/log.h>
-#include <devman.h>
-#include <ipc/devman.h>
-#include <ipc/dev_iface.h>
-#include <ops/hw_res.h>
-#include <device/hw_res.h>
-
-#define NAME "rootpc"
-
-/** Obtain function soft-state from DDF function node */
-#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
-
-typedef struct rootpc_fun {
-	hw_resource_list_t hw_resources;
-} rootpc_fun_t;
-
-static int rootpc_add_device(ddf_dev_t *dev);
-static void root_pc_init(void);
-
-/** The root device driver's standard operations. */
-static driver_ops_t rootpc_ops = {
-	.add_device = &rootpc_add_device
-};
-
-/** The root device driver structure. */
-static driver_t rootpc_driver = {
-	.name = NAME,
-	.driver_ops = &rootpc_ops
-};
-
-static hw_resource_t pci_conf_regs = {
-	.type = IO_RANGE,
-	.res.io_range = {
-		.address = 0xCF8,
-		.size = 8,
-		.endianness = LITTLE_ENDIAN
-	}
-};
-
-static rootpc_fun_t pci_data = {
-	.hw_resources = {
-		1,
-		&pci_conf_regs
-	}
-};
-
-static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
-{
-	rootpc_fun_t *fun = ROOTPC_FUN(fnode);
-	
-	assert(fun != NULL);
-	return &fun->hw_resources;
-}
-
-static bool rootpc_enable_interrupt(ddf_fun_t *fun)
-{
-	/* TODO */
-	
-	return false;
-}
-
-static hw_res_ops_t fun_hw_res_ops = {
-	&rootpc_get_resources,
-	&rootpc_enable_interrupt
-};
-
-/* Initialized in root_pc_init() function. */
-static ddf_dev_ops_t rootpc_fun_ops;
-
-static bool
-rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
-    rootpc_fun_t *fun)
-{
-	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
-	
-	ddf_fun_t *fnode = NULL;
-	match_id_t *match_id = NULL;
-	
-	/* Create new device. */
-	fnode = ddf_fun_create(dev, fun_inner, name);
-	if (fnode == NULL)
-		goto failure;
-	
-	fnode->driver_data = fun;
-	
-	/* Initialize match id list */
-	match_id = create_match_id();
-	if (match_id == NULL)
-		goto failure;
-	
-	match_id->id = str_match_id;
-	match_id->score = 100;
-	add_match_id(&fnode->match_ids, match_id);
-	
-	/* Set provided operations to the device. */
-	fnode->ops = &rootpc_fun_ops;
-	
-	/* Register function. */
-	if (ddf_fun_bind(fnode) != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
-		goto failure;
-	}
-	
-	return true;
-	
-failure:
-	if (match_id != NULL)
-		match_id->id = NULL;
-	
-	if (fnode != NULL)
-		ddf_fun_destroy(fnode);
-	
-	ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name);
-	
-	return false;
-}
-
-static bool rootpc_add_functions(ddf_dev_t *dev)
-{
-	return rootpc_add_fun(dev, "pci0", "intel_pci", &pci_data);
-}
-
-/** Get the root device.
- *
- * @param dev		The device which is root of the whole device tree (both
- *			of HW and pseudo devices).
- * @return		Zero on success, negative error number otherwise.
- */
-static int rootpc_add_device(ddf_dev_t *dev)
-{
-	ddf_msg(LVL_DEBUG, "rootpc_add_device, device handle = %d",
-	    (int)dev->handle);
-	
-	/* Register functions. */
-	if (!rootpc_add_functions(dev)) {
-		ddf_msg(LVL_ERROR, "Failed to add functions for PC platform.");
-	}
-	
-	return EOK;
-}
-
-static void root_pc_init(void)
-{
-	ddf_log_init(NAME, LVL_ERROR);
-	rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS PC platform driver\n");
-	root_pc_init();
-	return ddf_driver_main(&rootpc_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/rootpc/rootpc.ma
===================================================================
--- uspace/drv/rootpc/rootpc.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 platform/pc
Index: pace/drv/rootvirt/Makefile
===================================================================
--- uspace/drv/rootvirt/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = rootvirt
-
-SOURCES = \
-	rootvirt.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/rootvirt/devices.def
===================================================================
--- uspace/drv/rootvirt/devices.def	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,34 +1,0 @@
-/*
- * Add list of virtual devices you want to launch driver for here.
- *
- * Unless the list is empty, the last item shall be followed by a comma.
- */
-#ifdef CONFIG_TEST_DRIVERS
-{
-	.name = "test1",
-	.match_id = "virtual&test1"
-},
-{
-	.name = "test2alpha",
-	.match_id = "virtual&test2"
-},
-{
-	.name = "test2bravo",
-	.match_id = "virtual&test2"
-},
-{
-	.name = "null",
-	.match_id = "virtual&test1"
-},
-{
-	.name = "test3",
-	.match_id = "virtual&test3"
-},
-#endif
-#ifdef CONFIG_RUN_VIRTUAL_USB_HC
-/* Virtual USB host controller. */
-{
-	.name = "usbhc",
-	.match_id = "usb&hc=vhc"
-},
-#endif
Index: pace/drv/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/rootvirt/rootvirt.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,153 +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.
- */
-
-/**
- * @defgroup rootvirt Root device driver for virtual devices.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/driver.h>
-#include <ddf/log.h>
-
-#define NAME "rootvirt"
-
-/** Virtual function entry */
-typedef struct {
-	/** Function name */
-	const char *name;
-	/** Function match ID */
-	const char *match_id;
-} virtual_function_t;
-
-/** List of existing virtual functions */
-virtual_function_t virtual_functions[] = {
-#include "devices.def"
-	/* Terminating item */
-	{
-		.name = NULL,
-		.match_id = NULL
-	}
-};
-
-static int rootvirt_add_device(ddf_dev_t *dev);
-
-static driver_ops_t rootvirt_ops = {
-	.add_device = &rootvirt_add_device
-};
-
-static driver_t rootvirt_driver = {
-	.name = NAME,
-	.driver_ops = &rootvirt_ops
-};
-
-/** Add function to the virtual device.
- *
- * @param vdev		The virtual device
- * @param vfun		Virtual function description
- * @return		EOK on success or negative error code.
- */
-static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
-{
-	ddf_fun_t *fun;
-	int rc;
-
-	ddf_msg(LVL_DEBUG, "Registering function `%s' (match \"%s\")",
-	    vfun->name, vfun->match_id);
-
-	fun = ddf_fun_create(vdev, fun_inner, vfun->name);
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function %s", vfun->name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
-		    vfun->name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function %s: %s",
-		    vfun->name, str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	ddf_msg(LVL_NOTE, "Registered child device `%s'", vfun->name);
-	return EOK;
-}
-
-static int rootvirt_add_device(ddf_dev_t *dev)
-{
-	static int instances = 0;
-
-	/*
-	 * Allow only single instance of root virtual device.
-	 */
-	instances++;
-	if (instances > 1) {
-		return ELIMIT;
-	}
-
-	ddf_msg(LVL_DEBUG, "add_device(handle=%d)", (int)dev->handle);
-
-	/*
-	 * Go through all virtual functions and try to add them.
-	 * We silently ignore failures.
-	 */
-	virtual_function_t *vfun = virtual_functions;
-	while (vfun->name != NULL) {
-		(void) rootvirt_add_fun(dev, vfun);
-		vfun++;
-	}
-
-	return EOK;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS virtual devices root driver\n");
-
-	ddf_log_init(NAME, LVL_ERROR);
-	return ddf_driver_main(&rootvirt_driver);
-}
-
-/**
- * @}
- */
-
Index: pace/drv/rootvirt/rootvirt.ma
===================================================================
--- uspace/drv/rootvirt/rootvirt.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 rootvirt
Index: uspace/drv/test/test1/Makefile
===================================================================
--- uspace/drv/test/test1/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test1/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = test1
+
+SOURCES = \
+	char.c \
+	test1.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/test/test1/char.c
===================================================================
--- uspace/drv/test/test1/char.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test1/char.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <mem.h>
+#include <ops/char_dev.h>
+
+#include "test1.h"
+
+static int impl_char_read(ddf_fun_t *fun, char *buf, size_t count) {
+	memset(buf, 0, count);
+	return count;
+}
+
+static int imp_char_write(ddf_fun_t *fun, char *buf, size_t count) {
+	return count;
+}
+
+static char_dev_ops_t char_dev_ops = {
+	.read = &impl_char_read,
+	.write = &imp_char_write
+};
+
+ddf_dev_ops_t char_device_ops = {
+	.interfaces[CHAR_DEV_IFACE] = &char_dev_ops
+};
+
Index: uspace/drv/test/test1/test1.c
===================================================================
--- uspace/drv/test/test1/test1.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test1/test1.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#include "test1.h"
+
+static int test1_add_device(ddf_dev_t *dev);
+
+static driver_ops_t driver_ops = {
+	.add_device = &test1_add_device
+};
+
+static driver_t test1_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+/** Register child and inform user about it.
+ *
+ * @param parent Parent device.
+ * @param message Message for the user.
+ * @param name Device name.
+ * @param match_id Device match id.
+ * @param score Device match score.
+ */
+static int register_fun_verbose(ddf_dev_t *parent, const char *message,
+    const char *name, const char *match_id, int match_score,
+    int expected_rc)
+{
+	ddf_fun_t *fun = NULL;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);
+
+	fun = ddf_fun_create(parent, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	rc = ddf_fun_add_match_id(fun, str_dup(match_id), match_score);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		goto leave;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		goto leave;
+	}
+
+	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
+	rc = EOK;
+
+leave:
+	if (rc != expected_rc) {
+		fprintf(stderr,
+		    NAME ": Unexpected error registering function `%s'.\n" 
+		    NAME ":     Expected \"%s\" but got \"%s\".\n",
+		    name, str_error(expected_rc), str_error(rc));
+	}
+
+	if ((rc != EOK) && (fun != NULL)) {
+		ddf_fun_destroy(fun);
+	}
+
+	return rc;
+}
+
+/** Callback when new device is passed to this driver.
+ * This function is the body of the test: it shall register new child
+ * (named `clone') that shall be driven by the same task. When the clone
+ * is added, it registers another child (named `child') that is also driven
+ * by this task. The conditions ensure that we do not recurse indefinitely.
+ * When successful, the device tree shall contain following fragment:
+ *
+ * /virtual/test1
+ * /virtual/test1/clone
+ * /virtual/test1/clone/child
+ *
+ * and devman shall not deadlock.
+ *
+ *
+ * @param dev New device.
+ * @return Error code reporting success of the operation.
+ */
+static int test1_add_device(ddf_dev_t *dev)
+{
+	ddf_fun_t *fun_a;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)",
+	    dev->name, (int) dev->handle);
+
+	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
+		return rc;
+	}
+
+	ddf_fun_add_to_class(fun_a, "virtual");
+
+	if (str_cmp(dev->name, "null") == 0) {
+		fun_a->ops = &char_device_ops;
+		ddf_fun_add_to_class(fun_a, "virt-null");
+	} else if (str_cmp(dev->name, "test1") == 0) {
+		(void) register_fun_verbose(dev,
+		    "cloning myself ;-)", "clone",
+		    "virtual&test1", 10, EOK);
+		(void) register_fun_verbose(dev,
+		    "cloning myself twice ;-)", "clone",
+		    "virtual&test1", 10, EEXISTS);
+	} else if (str_cmp(dev->name, "clone") == 0) {
+		(void) register_fun_verbose(dev,
+		    "run by the same task", "child",
+		    "virtual&test1&child", 10, EOK);
+	}
+
+	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev->name);
+
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS test1 virtual device driver\n");
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&test1_driver);
+}
+
Index: uspace/drv/test/test1/test1.h
===================================================================
--- uspace/drv/test/test1/test1.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test1/test1.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/** @file
+ */
+#ifndef DRV_TEST1_TEST1_H_
+#define DRV_TEST1_TEST1_H_
+
+#include <ddf/driver.h>
+
+#define NAME "test1"
+
+extern ddf_dev_ops_t char_device_ops;
+
+#endif
Index: uspace/drv/test/test1/test1.ma
===================================================================
--- uspace/drv/test/test1/test1.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test1/test1.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,2 @@
+10 virtual&test1
+10 virtual&test1&child
Index: uspace/drv/test/test2/Makefile
===================================================================
--- uspace/drv/test/test2/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test2/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = test2
+
+SOURCES = \
+	test2.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/test/test2/test2.c
===================================================================
--- uspace/drv/test/test2/test2.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test2/test2.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#define NAME "test2"
+
+static int test2_add_device(ddf_dev_t *dev);
+
+static driver_ops_t driver_ops = {
+	.add_device = &test2_add_device
+};
+
+static driver_t test2_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+/** Register child and inform user about it.
+ *
+ * @param parent Parent device.
+ * @param message Message for the user.
+ * @param name Device name.
+ * @param match_id Device match id.
+ * @param score Device match score.
+ */
+static int register_fun_verbose(ddf_dev_t *parent, const char *message,
+    const char *name, const char *match_id, int match_score)
+{
+	ddf_fun_t *fun;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);
+
+	fun = ddf_fun_create(parent, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, match_score);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
+	return EOK;
+}
+
+/** Add child devices after some sleep.
+ *
+ * @param arg Parent device structure (ddf_dev_t *).
+ * @return Always EOK.
+ */
+static int postponed_birth(void *arg)
+{
+	ddf_dev_t *dev = (ddf_dev_t *) arg;
+	ddf_fun_t *fun_a;
+	int rc;
+
+	async_usleep(1000);
+
+	(void) register_fun_verbose(dev, "child driven by the same task",
+	    "child", "virtual&test2", 10);
+	(void) register_fun_verbose(dev, "child driven by test1",
+	    "test1", "virtual&test1", 10);
+
+	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
+		return rc;
+	}
+
+	ddf_fun_add_to_class(fun_a, "virtual");
+
+	return EOK;
+}
+
+static int test2_add_device(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "test2_add_device(name=\"%s\", handle=%d)",
+	    dev->name, (int) dev->handle);
+
+	if (str_cmp(dev->name, "child") != 0) {
+		fid_t postpone = fibril_create(postponed_birth, dev);
+		if (postpone == 0) {
+			ddf_msg(LVL_ERROR, "fibril_create() failed.");
+			return ENOMEM;
+		}
+		fibril_add_ready(postpone);
+	} else {
+		(void) register_fun_verbose(dev, "child without available driver",
+		    "ERROR", "non-existent.match.id", 10);
+	}
+
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS test2 virtual device driver\n");
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&test2_driver);
+}
+
+
Index: uspace/drv/test/test2/test2.ma
===================================================================
--- uspace/drv/test/test2/test2.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test2/test2.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 virtual&test2
Index: uspace/drv/test/test3/Makefile
===================================================================
--- uspace/drv/test/test3/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test3/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = test3
+
+SOURCES = \
+	test3.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/test/test3/test3.c
===================================================================
--- uspace/drv/test/test3/test3.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test3/test3.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#define NAME "test3"
+
+static int test3_add_device(ddf_dev_t *dev);
+
+static driver_ops_t driver_ops = {
+	.add_device = &test3_add_device
+};
+
+static driver_t test3_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+static int register_fun_and_add_to_class(ddf_dev_t *parent,
+     const char *base_name, size_t index, const char *class_name)
+{
+	ddf_fun_t *fun = NULL;
+	int rc;
+	char *fun_name = NULL;
+	
+	rc = asprintf(&fun_name, "%s%zu", base_name, index);
+	if (rc < 0) {
+		ddf_msg(LVL_ERROR, "Failed to format string: %s", str_error(rc));
+		goto leave;
+	}
+	
+	fun = ddf_fun_create(parent, fun_exposed, fun_name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", fun_name);
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", fun_name,
+		    str_error(rc));
+		goto leave;
+	}
+	
+	ddf_fun_add_to_class(fun, class_name);
+
+	ddf_msg(LVL_NOTE, "Registered exposed function `%s'.", fun_name);
+
+leave:	
+	free(fun_name);
+	
+	if ((rc != EOK) && (fun != NULL)) {
+		ddf_fun_destroy(fun);
+	}
+	
+	return rc;
+}
+
+static int test3_add_device(ddf_dev_t *dev)
+{
+	int rc = EOK;
+
+	ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)",
+	    dev->name, (int) dev->handle);
+
+	size_t i;
+	for (i = 0; i < 20; i++) {
+		rc = register_fun_and_add_to_class(dev,
+		    "test3_", i, "test3");
+		if (rc != EOK) {
+			break;
+		}
+	}
+	
+	return rc;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS test3 virtual device driver\n");
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&test3_driver);
+}
+
Index: uspace/drv/test/test3/test3.ma
===================================================================
--- uspace/drv/test/test3/test3.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/drv/test/test3/test3.ma	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,1 @@
+10 virtual&test3
Index: pace/drv/test1/Makefile
===================================================================
--- uspace/drv/test1/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,38 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = test1
-
-SOURCES = \
-	char.c \
-	test1.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/test1/char.c
===================================================================
--- uspace/drv/test1/char.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,56 +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.
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <mem.h>
-#include <ops/char_dev.h>
-
-#include "test1.h"
-
-static int impl_char_read(ddf_fun_t *fun, char *buf, size_t count) {
-	memset(buf, 0, count);
-	return count;
-}
-
-static int imp_char_write(ddf_fun_t *fun, char *buf, size_t count) {
-	return count;
-}
-
-static char_dev_ops_t char_dev_ops = {
-	.read = &impl_char_read,
-	.write = &imp_char_write
-};
-
-ddf_dev_ops_t char_device_ops = {
-	.interfaces[CHAR_DEV_IFACE] = &char_dev_ops
-};
-
Index: pace/drv/test1/test1.c
===================================================================
--- uspace/drv/test1/test1.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,174 +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.
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/driver.h>
-#include <ddf/log.h>
-
-#include "test1.h"
-
-static int test1_add_device(ddf_dev_t *dev);
-
-static driver_ops_t driver_ops = {
-	.add_device = &test1_add_device
-};
-
-static driver_t test1_driver = {
-	.name = NAME,
-	.driver_ops = &driver_ops
-};
-
-/** Register child and inform user about it.
- *
- * @param parent Parent device.
- * @param message Message for the user.
- * @param name Device name.
- * @param match_id Device match id.
- * @param score Device match score.
- */
-static int register_fun_verbose(ddf_dev_t *parent, const char *message,
-    const char *name, const char *match_id, int match_score,
-    int expected_rc)
-{
-	ddf_fun_t *fun = NULL;
-	int rc;
-
-	ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);
-
-	fun = ddf_fun_create(parent, fun_inner, name);
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
-		rc = ENOMEM;
-		goto leave;
-	}
-
-	rc = ddf_fun_add_match_id(fun, str_dup(match_id), match_score);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
-		    name);
-		goto leave;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
-		    str_error(rc));
-		goto leave;
-	}
-
-	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
-	rc = EOK;
-
-leave:
-	if (rc != expected_rc) {
-		fprintf(stderr,
-		    NAME ": Unexpected error registering function `%s'.\n" 
-		    NAME ":     Expected \"%s\" but got \"%s\".\n",
-		    name, str_error(expected_rc), str_error(rc));
-	}
-
-	if ((rc != EOK) && (fun != NULL)) {
-		ddf_fun_destroy(fun);
-	}
-
-	return rc;
-}
-
-/** Callback when new device is passed to this driver.
- * This function is the body of the test: it shall register new child
- * (named `clone') that shall be driven by the same task. When the clone
- * is added, it registers another child (named `child') that is also driven
- * by this task. The conditions ensure that we do not recurse indefinitely.
- * When successful, the device tree shall contain following fragment:
- *
- * /virtual/test1
- * /virtual/test1/clone
- * /virtual/test1/clone/child
- *
- * and devman shall not deadlock.
- *
- *
- * @param dev New device.
- * @return Error code reporting success of the operation.
- */
-static int test1_add_device(ddf_dev_t *dev)
-{
-	ddf_fun_t *fun_a;
-	int rc;
-
-	ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
-
-	fun_a = ddf_fun_create(dev, fun_exposed, "a");
-	if (fun_a == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_bind(fun_a);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
-		return rc;
-	}
-
-	ddf_fun_add_to_class(fun_a, "virtual");
-
-	if (str_cmp(dev->name, "null") == 0) {
-		fun_a->ops = &char_device_ops;
-		ddf_fun_add_to_class(fun_a, "virt-null");
-	} else if (str_cmp(dev->name, "test1") == 0) {
-		(void) register_fun_verbose(dev,
-		    "cloning myself ;-)", "clone",
-		    "virtual&test1", 10, EOK);
-		(void) register_fun_verbose(dev,
-		    "cloning myself twice ;-)", "clone",
-		    "virtual&test1", 10, EEXISTS);
-	} else if (str_cmp(dev->name, "clone") == 0) {
-		(void) register_fun_verbose(dev,
-		    "run by the same task", "child",
-		    "virtual&test1&child", 10, EOK);
-	}
-
-	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev->name);
-
-	return EOK;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS test1 virtual device driver\n");
-	ddf_log_init(NAME, LVL_ERROR);
-	return ddf_driver_main(&test1_driver);
-}
-
Index: pace/drv/test1/test1.h
===================================================================
--- uspace/drv/test1/test1.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,40 +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.
- */
-
-/** @file
- */
-#ifndef DRV_TEST1_TEST1_H_
-#define DRV_TEST1_TEST1_H_
-
-#include <ddf/driver.h>
-
-#define NAME "test1"
-
-extern ddf_dev_ops_t char_device_ops;
-
-#endif
Index: pace/drv/test1/test1.ma
===================================================================
--- uspace/drv/test1/test1.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,2 +1,0 @@
-10 virtual&test1
-10 virtual&test1&child
Index: pace/drv/test2/Makefile
===================================================================
--- uspace/drv/test2/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = test2
-
-SOURCES = \
-	test2.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/test2/test2.c
===================================================================
--- uspace/drv/test2/test2.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,157 +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.
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/driver.h>
-#include <ddf/log.h>
-
-#define NAME "test2"
-
-static int test2_add_device(ddf_dev_t *dev);
-
-static driver_ops_t driver_ops = {
-	.add_device = &test2_add_device
-};
-
-static driver_t test2_driver = {
-	.name = NAME,
-	.driver_ops = &driver_ops
-};
-
-/** Register child and inform user about it.
- *
- * @param parent Parent device.
- * @param message Message for the user.
- * @param name Device name.
- * @param match_id Device match id.
- * @param score Device match score.
- */
-static int register_fun_verbose(ddf_dev_t *parent, const char *message,
-    const char *name, const char *match_id, int match_score)
-{
-	ddf_fun_t *fun;
-	int rc;
-
-	ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);
-
-	fun = ddf_fun_create(parent, fun_inner, name);
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, match_id, match_score);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
-		    name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
-	return EOK;
-}
-
-/** Add child devices after some sleep.
- *
- * @param arg Parent device structure (ddf_dev_t *).
- * @return Always EOK.
- */
-static int postponed_birth(void *arg)
-{
-	ddf_dev_t *dev = (ddf_dev_t *) arg;
-	ddf_fun_t *fun_a;
-	int rc;
-
-	async_usleep(1000);
-
-	(void) register_fun_verbose(dev, "child driven by the same task",
-	    "child", "virtual&test2", 10);
-	(void) register_fun_verbose(dev, "child driven by test1",
-	    "test1", "virtual&test1", 10);
-
-	fun_a = ddf_fun_create(dev, fun_exposed, "a");
-	if (fun_a == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_bind(fun_a);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
-		return rc;
-	}
-
-	ddf_fun_add_to_class(fun_a, "virtual");
-
-	return EOK;
-}
-
-static int test2_add_device(ddf_dev_t *dev)
-{
-	ddf_msg(LVL_DEBUG, "test2_add_device(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
-
-	if (str_cmp(dev->name, "child") != 0) {
-		fid_t postpone = fibril_create(postponed_birth, dev);
-		if (postpone == 0) {
-			ddf_msg(LVL_ERROR, "fibril_create() failed.");
-			return ENOMEM;
-		}
-		fibril_add_ready(postpone);
-	} else {
-		(void) register_fun_verbose(dev, "child without available driver",
-		    "ERROR", "non-existent.match.id", 10);
-	}
-
-	return EOK;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS test2 virtual device driver\n");
-	ddf_log_init(NAME, LVL_ERROR);
-	return ddf_driver_main(&test2_driver);
-}
-
-
Index: pace/drv/test2/test2.ma
===================================================================
--- uspace/drv/test2/test2.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 virtual&test2
Index: pace/drv/test3/Makefile
===================================================================
--- uspace/drv/test3/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = test3
-
-SOURCES = \
-	test3.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/test3/test3.c
===================================================================
--- uspace/drv/test3/test3.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,118 +1,0 @@
-/*
- * 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.
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/driver.h>
-#include <ddf/log.h>
-
-#define NAME "test3"
-
-static int test3_add_device(ddf_dev_t *dev);
-
-static driver_ops_t driver_ops = {
-	.add_device = &test3_add_device
-};
-
-static driver_t test3_driver = {
-	.name = NAME,
-	.driver_ops = &driver_ops
-};
-
-static int register_fun_and_add_to_class(ddf_dev_t *parent,
-     const char *base_name, size_t index, const char *class_name)
-{
-	ddf_fun_t *fun = NULL;
-	int rc;
-	char *fun_name = NULL;
-	
-	rc = asprintf(&fun_name, "%s%zu", base_name, index);
-	if (rc < 0) {
-		ddf_msg(LVL_ERROR, "Failed to format string: %s", str_error(rc));
-		goto leave;
-	}
-	
-	fun = ddf_fun_create(parent, fun_exposed, fun_name);
-	if (fun == NULL) {
-		ddf_msg(LVL_ERROR, "Failed creating function %s", fun_name);
-		rc = ENOMEM;
-		goto leave;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", fun_name,
-		    str_error(rc));
-		goto leave;
-	}
-	
-	ddf_fun_add_to_class(fun, class_name);
-
-	ddf_msg(LVL_NOTE, "Registered exposed function `%s'.", fun_name);
-
-leave:	
-	free(fun_name);
-	
-	if ((rc != EOK) && (fun != NULL)) {
-		ddf_fun_destroy(fun);
-	}
-	
-	return rc;
-}
-
-static int test3_add_device(ddf_dev_t *dev)
-{
-	int rc = EOK;
-
-	ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)",
-	    dev->name, (int) dev->handle);
-
-	size_t i;
-	for (i = 0; i < 20; i++) {
-		rc = register_fun_and_add_to_class(dev,
-		    "test3_", i, "test3");
-		if (rc != EOK) {
-			break;
-		}
-	}
-	
-	return rc;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS test3 virtual device driver\n");
-	ddf_log_init(NAME, LVL_ERROR);
-	return ddf_driver_main(&test3_driver);
-}
-
Index: pace/drv/test3/test3.ma
===================================================================
--- uspace/drv/test3/test3.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 virtual&test3
Index: pace/drv/uhci_hcd/Makefile
===================================================================
--- uspace/drv/uhci_hcd/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,53 +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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBHOST_PREFIX)/libusbhost.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBHOST_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = uhci_hcd
-
-SOURCES = \
-	iface.c \
-	main.c \
-	transfer_list.c \
-	uhci.c \
-	hc.c \
-	root_hub.c \
-	hw_struct/transfer_descriptor.c \
-	pci.c \
-	batch.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/uhci_hcd/batch.c
===================================================================
--- uspace/drv/uhci_hcd/batch.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,424 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver USB transfer structure
- */
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/usb.h>
-#include <usb/debug.h>
-
-#include "batch.h"
-#include "transfer_list.h"
-#include "hw_struct/transfer_descriptor.h"
-#include "utils/malloc32.h"
-
-#define DEFAULT_ERROR_COUNT 3
-
-/** UHCI specific data required for USB transfer */
-typedef struct uhci_transfer_batch {
-	/** Queue head
-	 * This QH is used to maintain UHCI schedule structure and the element
-	 * pointer points to the first TD of this batch.
-	 */
-	qh_t *qh;
-	/** List of TDs needed for the transfer */
-	td_t *tds;
-	/** Number of TDs used by the transfer */
-	size_t td_count;
-	/** Data buffer, must be accessible by the UHCI hw */
-	void *device_buffer;
-} uhci_transfer_batch_t;
-/*----------------------------------------------------------------------------*/
-static void batch_control(usb_transfer_batch_t *instance,
-    usb_packet_id data_stage, usb_packet_id status_stage);
-static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
-/*----------------------------------------------------------------------------*/
-/** Safely destructs uhci_transfer_batch_t structure
- *
- * @param[in] uhci_batch Instance to destroy.
- */
-static void uhci_transfer_batch_dispose(void *uhci_batch)
-{
-	uhci_transfer_batch_t *instance = uhci_batch;
-	assert(instance);
-	free32(instance->device_buffer);
-	free(instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Allocate memory and initialize internal data structure.
- *
- * @param[in] fun DDF function to pass to callback.
- * @param[in] ep Communication target
- * @param[in] buffer Data source/destination.
- * @param[in] buffer_size Size of the buffer.
- * @param[in] setup_buffer Setup data source (if not NULL)
- * @param[in] setup_size Size of setup_buffer (should be always 8)
- * @param[in] func_in function to call on inbound transfer completion
- * @param[in] func_out function to call on outbound transfer completion
- * @param[in] arg additional parameter to func_in or func_out
- * @return Valid pointer if all structures were successfully created,
- * NULL otherwise.
- *
- * Determines the number of needed transfer descriptors (TDs).
- * Prepares a transport buffer (that is accessible by the hardware).
- * Initializes parameters needed for the transfer and callback.
- */
-usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
-    char *buffer, size_t buffer_size,
-    const 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(ep);
-	assert(func_in == NULL || func_out == NULL);
-	assert(func_in != NULL || func_out != NULL);
-
-#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
-	if (ptr == NULL) { \
-		usb_log_error(message); \
-		if (uhci_data) { \
-			uhci_transfer_batch_dispose(uhci_data); \
-		} \
-		return NULL; \
-	} else (void)0
-
-	uhci_transfer_batch_t *uhci_data =
-	    malloc(sizeof(uhci_transfer_batch_t));
-	CHECK_NULL_DISPOSE_RETURN(uhci_data,
-	    "Failed to allocate UHCI batch.\n");
-	bzero(uhci_data, sizeof(uhci_transfer_batch_t));
-
-	uhci_data->td_count =
-	    (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
-	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
-		uhci_data->td_count += 2;
-	}
-
-	assert((sizeof(td_t) % 16) == 0);
-	const size_t total_size = (sizeof(td_t) * uhci_data->td_count)
-	    + sizeof(qh_t) + setup_size + buffer_size;
-	uhci_data->device_buffer = malloc32(total_size);
-	CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer,
-	    "Failed to allocate UHCI buffer.\n");
-	bzero(uhci_data->device_buffer, total_size);
-
-	uhci_data->tds = uhci_data->device_buffer;
-	uhci_data->qh =
-	    (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count));
-
-	qh_init(uhci_data->qh);
-	qh_set_element_td(uhci_data->qh, uhci_data->tds);
-
-	usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
-	CHECK_NULL_DISPOSE_RETURN(instance,
-	    "Failed to allocate batch instance.\n");
-	void *setup =
-	    uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)
-	    + sizeof(qh_t);
-	void *data_buffer = setup + setup_size;
-	usb_target_t target =
-	    { .address = ep->address, .endpoint = ep->endpoint };
-	usb_transfer_batch_init(instance, ep, buffer, data_buffer, buffer_size,
-	    setup, setup_size, func_in, func_out, arg, fun,
-	    uhci_data, uhci_transfer_batch_dispose);
-
-	memcpy(instance->setup_buffer, setup_buffer, setup_size);
-	usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
-	    instance, target.address, target.endpoint);
-	return instance;
-}
-/*----------------------------------------------------------------------------*/
-/** Check batch TDs for activity.
- *
- * @param[in] instance Batch structure to use.
- * @return False, if there is an active TD, true otherwise.
- *
- * Walk all TDs. Stop with false if there is an active one (it is to be
- * processed). Stop with true if an error is found. Return true if the last TD
- * is reached.
- */
-bool batch_is_complete(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	uhci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-
-	usb_log_debug2("Batch(%p) checking %zu transfer(s) for completion.\n",
-	    instance, data->td_count);
-	instance->transfered_size = 0;
-	size_t i = 0;
-	for (;i < data->td_count; ++i) {
-		if (td_is_active(&data->tds[i])) {
-			return false;
-		}
-
-		instance->error = td_status(&data->tds[i]);
-		if (instance->error != EOK) {
-			usb_log_debug("Batch(%p) found error TD(%zu):%"
-			    PRIx32 ".\n", instance, i, data->tds[i].status);
-			td_print_status(&data->tds[i]);
-
-			assert(instance->ep != NULL);
-			endpoint_toggle_set(instance->ep,
-			    td_toggle(&data->tds[i]));
-			if (i > 0)
-				goto substract_ret;
-			return true;
-		}
-
-		instance->transfered_size += td_act_size(&data->tds[i]);
-		if (td_is_short(&data->tds[i]))
-			goto substract_ret;
-	}
-substract_ret:
-	instance->transfered_size -= instance->setup_size;
-	return true;
-}
-/*----------------------------------------------------------------------------*/
-/** Prepares control write transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Uses generic control function with pids OUT and IN.
- */
-void batch_control_write(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	/* We are data out, we are supposed to provide data */
-	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
-	batch_control(instance, USB_PID_OUT, USB_PID_IN);
-	instance->next_step = usb_transfer_batch_call_out_and_dispose;
-	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepares control read transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Uses generic control with pids IN and OUT.
- */
-void batch_control_read(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	batch_control(instance, USB_PID_IN, USB_PID_OUT);
-	instance->next_step = usb_transfer_batch_call_in_and_dispose;
-	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare interrupt in transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transfer with PID_IN.
- */
-void batch_interrupt_in(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	batch_data(instance, USB_PID_IN);
-	instance->next_step = usb_transfer_batch_call_in_and_dispose;
-	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare interrupt out transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transfer with PID_OUT.
- */
-void batch_interrupt_out(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	/* We are data out, we are supposed to provide data */
-	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
-	batch_data(instance, USB_PID_OUT);
-	instance->next_step = usb_transfer_batch_call_out_and_dispose;
-	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare bulk in transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transfer with PID_IN.
- */
-void batch_bulk_in(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	batch_data(instance, USB_PID_IN);
-	instance->next_step = usb_transfer_batch_call_in_and_dispose;
-	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare bulk out transfer.
- *
- * @param[in] instance Batch structure to use.
- *
- * Data transfer with PID_OUT.
- */
-void batch_bulk_out(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	/* We are data out, we are supposed to provide data */
-	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
-	batch_data(instance, USB_PID_OUT);
-	instance->next_step = usb_transfer_batch_call_out_and_dispose;
-	usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare generic data transfer
- *
- * @param[in] instance Batch structure to use.
- * @param[in] pid Pid to use for data transactions.
- *
- * Transactions with alternating toggle bit and supplied pid value.
- * The last transfer is marked with IOC flag.
- */
-void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid)
-{
-	assert(instance);
-	uhci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-
-	const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
-	int toggle = endpoint_toggle_get(instance->ep);
-	assert(toggle == 0 || toggle == 1);
-
-	size_t td = 0;
-	size_t remain_size = instance->buffer_size;
-	char *buffer = instance->data_buffer;
-	while (remain_size > 0) {
-		const size_t packet_size =
-		    (instance->ep->max_packet_size > remain_size) ?
-		    remain_size : instance->ep->max_packet_size;
-
-		td_t *next_td = (td + 1 < data->td_count)
-		    ? &data->tds[td + 1] : NULL;
-
-
-		usb_target_t target =
-		    { instance->ep->address, instance->ep->endpoint };
-
-		assert(td < data->td_count);
-		td_init(
-		    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
-		    toggle, false, low_speed, target, pid, buffer, next_td);
-
-		++td;
-		toggle = 1 - toggle;
-		buffer += packet_size;
-		assert(packet_size <= remain_size);
-		remain_size -= packet_size;
-	}
-	td_set_ioc(&data->tds[td - 1]);
-	endpoint_toggle_set(instance->ep, toggle);
-}
-/*----------------------------------------------------------------------------*/
-/** Prepare generic control transfer
- *
- * @param[in] instance Batch structure to use.
- * @param[in] data_stage Pid to use for data tds.
- * @param[in] status_stage Pid to use for data tds.
- *
- * Setup stage with toggle 0 and USB_PID_SETUP.
- * Data stage with alternating toggle and pid supplied by parameter.
- * Status stage with toggle 1 and pid supplied by parameter.
- * The last transfer is marked with IOC.
- */
-void batch_control(usb_transfer_batch_t *instance,
-   usb_packet_id data_stage, usb_packet_id status_stage)
-{
-	assert(instance);
-	uhci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-	assert(data->td_count >= 2);
-
-	const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
-	const usb_target_t target =
-	    { instance->ep->address, instance->ep->endpoint };
-
-	/* setup stage */
-	td_init(
-	    data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
-	    low_speed, target, USB_PID_SETUP, instance->setup_buffer,
-	    &data->tds[1]);
-
-	/* data stage */
-	size_t td = 1;
-	unsigned toggle = 1;
-	size_t remain_size = instance->buffer_size;
-	char *buffer = instance->data_buffer;
-	while (remain_size > 0) {
-		const size_t packet_size =
-		    (instance->ep->max_packet_size > remain_size) ?
-		    remain_size : instance->ep->max_packet_size;
-
-		td_init(
-		    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
-		    toggle, false, low_speed, target, data_stage,
-		    buffer, &data->tds[td + 1]);
-
-		++td;
-		toggle = 1 - toggle;
-		buffer += packet_size;
-		assert(td < data->td_count);
-		assert(packet_size <= remain_size);
-		remain_size -= packet_size;
-	}
-
-	/* status stage */
-	assert(td == data->td_count - 1);
-
-	td_init(
-	    &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
-	    target, status_stage, NULL, NULL);
-	td_set_ioc(&data->tds[td]);
-
-	usb_log_debug2("Control last TD status: %x.\n",
-	    data->tds[td].status);
-}
-/*----------------------------------------------------------------------------*/
-/** Provides access to QH data structure.
- *
- * @param[in] instance Batch pointer to use.
- * @return Pointer to the QH used by the batch.
- */
-qh_t * batch_qh(usb_transfer_batch_t *instance)
-{
-	assert(instance);
-	uhci_transfer_batch_t *data = instance->private_data;
-	assert(data);
-	return data->qh;
-}
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/batch.h
===================================================================
--- uspace/drv/uhci_hcd/batch.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,65 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver USB tranfer helper functions
- */
-#ifndef DRV_UHCI_BATCH_H
-#define DRV_UHCI_BATCH_H
-
-#include <usb/host/batch.h>
-
-#include "hw_struct/queue_head.h"
-
-usb_transfer_batch_t * batch_get(
-    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
-    const 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);
-
-void batch_dispose(usb_transfer_batch_t *instance);
-
-bool batch_is_complete(usb_transfer_batch_t *instance);
-
-void batch_control_write(usb_transfer_batch_t *instance);
-void batch_control_read(usb_transfer_batch_t *instance);
-
-void batch_interrupt_in(usb_transfer_batch_t *instance);
-void batch_interrupt_out(usb_transfer_batch_t *instance);
-
-void batch_bulk_in(usb_transfer_batch_t *instance);
-void batch_bulk_out(usb_transfer_batch_t *instance);
-
-qh_t * batch_qh(usb_transfer_batch_t *instance);
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/hc.c
===================================================================
--- uspace/drv/uhci_hcd/hc.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,474 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI Host controller driver routines
- */
-#include <errno.h>
-#include <str_error.h>
-#include <adt/list.h>
-#include <libarch/ddi.h>
-
-#include <usb/debug.h>
-#include <usb/usb.h>
-
-#include "hc.h"
-
-#define UHCI_INTR_ALLOW_INTERRUPTS \
-    (UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET)
-#define UHCI_STATUS_USED_INTERRUPTS \
-    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
-
-
-static int hc_init_transfer_lists(hc_t *instance);
-static int hc_init_mem_structures(hc_t *instance);
-static void hc_init_hw(hc_t *instance);
-
-static int hc_interrupt_emulator(void *arg);
-static int hc_debug_checker(void *arg);
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI hc driver structure
- *
- * @param[in] instance Memory place to initialize.
- * @param[in] regs Address of I/O control registers.
- * @param[in] reg_size Size of I/O control registers.
- * @param[in] interrupts True if hw interrupts should be used.
- * @return Error code.
- * @note Should be called only once on any structure.
- *
- * Initializes memory structures, starts up hw, and launches debugger and
- * interrupt fibrils.
- */
-int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
-{
-	assert(reg_size >= sizeof(regs_t));
-	int ret;
-
-#define CHECK_RET_RETURN(ret, message...) \
-	if (ret != EOK) { \
-		usb_log_error(message); \
-		return ret; \
-	} else (void) 0
-
-	instance->hw_interrupts = interrupts;
-	instance->hw_failures = 0;
-
-	/* allow access to hc control registers */
-	regs_t *io;
-	ret = pio_enable(regs, reg_size, (void **)&io);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to gain access to registers at %p: %s.\n",
-	    ret, io, str_error(ret));
-	instance->registers = io;
-	usb_log_debug("Device registers at %p (%zuB) accessible.\n",
-	    io, reg_size);
-
-	ret = hc_init_mem_structures(instance);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to initialize UHCI memory structures: %s.\n",
-	    ret, str_error(ret));
-
-	hc_init_hw(instance);
-	if (!interrupts) {
-		instance->interrupt_emulator =
-		    fibril_create(hc_interrupt_emulator, instance);
-		fibril_add_ready(instance->interrupt_emulator);
-	}
-	(void)hc_debug_checker;
-
-	return EOK;
-#undef CHECK_RET_DEST_FUN_RETURN
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI hc hw resources.
- *
- * @param[in] instance UHCI structure to use.
- * For magic values see UHCI Design Guide
- */
-void hc_init_hw(hc_t *instance)
-{
-	assert(instance);
-	regs_t *registers = instance->registers;
-
-	/* Reset everything, who knows what touched it before us */
-	pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
-	async_usleep(10000); /* 10ms according to USB spec */
-	pio_write_16(&registers->usbcmd, 0);
-
-	/* Reset hc, all states and counters */
-	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
-	do { async_usleep(10); }
-	while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
-
-	/* Set frame to exactly 1ms */
-	pio_write_8(&registers->sofmod, 64);
-
-	/* Set frame list pointer */
-	const uint32_t pa = addr_to_phys(instance->frame_list);
-	pio_write_32(&registers->flbaseadd, pa);
-
-	if (instance->hw_interrupts) {
-		/* Enable all interrupts, but resume interrupt */
-		pio_write_16(&instance->registers->usbintr,
-		    UHCI_INTR_ALLOW_INTERRUPTS);
-	}
-
-	const uint16_t status = pio_read_16(&registers->usbcmd);
-	if (status != 0)
-		usb_log_warning("Previous command value: %x.\n", status);
-
-	/* Start the hc with large(64B) packet FSBR */
-	pio_write_16(&registers->usbcmd,
-	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI hc memory structures.
- *
- * @param[in] instance UHCI structure to use.
- * @return Error code
- * @note Should be called only once on any structure.
- *
- * Structures:
- *  - interrupt code (I/O addressses are customized per instance)
- *  - transfer lists (queue heads need to be accessible by the hw)
- *  - frame list page (needs to be one UHCI hw accessible 4K page)
- */
-int hc_init_mem_structures(hc_t *instance)
-{
-	assert(instance);
-#define CHECK_RET_RETURN(ret, message...) \
-	if (ret != EOK) { \
-		usb_log_error(message); \
-		return ret; \
-	} else (void) 0
-
-	/* Init interrupt code */
-	instance->interrupt_code.cmds = instance->interrupt_commands;
-	{
-		/* Read status register */
-		instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;
-		instance->interrupt_commands[0].dstarg = 1;
-		instance->interrupt_commands[0].addr =
-		    &instance->registers->usbsts;
-
-		/* Test whether we are the interrupt cause */
-		instance->interrupt_commands[1].cmd = CMD_BTEST;
-		instance->interrupt_commands[1].value =
-		    UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;
-		instance->interrupt_commands[1].srcarg = 1;
-		instance->interrupt_commands[1].dstarg = 2;
-
-		/* Predicate cleaning and accepting */
-		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
-		instance->interrupt_commands[2].value = 2;
-		instance->interrupt_commands[2].srcarg = 2;
-
-		/* Write clean status register */
-		instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;
-		instance->interrupt_commands[3].srcarg = 1;
-		instance->interrupt_commands[3].addr =
-		    &instance->registers->usbsts;
-
-		/* Accept interrupt */
-		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
-
-		instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;
-	}
-
-	/* Init transfer lists */
-	int ret = hc_init_transfer_lists(instance);
-	CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
-	usb_log_debug("Initialized transfer lists.\n");
-
-	/* Init USB frame list page*/
-	instance->frame_list = get_page();
-	ret = instance->frame_list ? EOK : ENOMEM;
-	CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
-	usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
-
-	/* Set all frames to point to the first queue head */
-	const uint32_t queue = LINK_POINTER_QH(
-	        addr_to_phys(instance->transfers_interrupt.queue_head));
-
-	unsigned i = 0;
-	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
-		instance->frame_list[i] = queue;
-	}
-
-	/* Init device keeper */
-	usb_device_keeper_init(&instance->manager);
-	usb_log_debug("Initialized device manager.\n");
-
-	ret = usb_endpoint_manager_init(&instance->ep_manager,
-	    BANDWIDTH_AVAILABLE_USB11);
-	CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
-	    str_error(ret));
-
-	return EOK;
-#undef CHECK_RET_RETURN
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI hc transfer lists.
- *
- * @param[in] instance UHCI structure to use.
- * @return Error code
- * @note Should be called only once on any structure.
- *
- * Initializes transfer lists and sets them in one chain to support proper
- * USB scheduling. Sets pointer table for quick access.
- */
-int hc_init_transfer_lists(hc_t *instance)
-{
-	assert(instance);
-#define SETUP_TRANSFER_LIST(type, name) \
-do { \
-	int ret = transfer_list_init(&instance->transfers_##type, name); \
-	if (ret != EOK) { \
-		usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
-		    ret, name, str_error(ret)); \
-		transfer_list_fini(&instance->transfers_bulk_full); \
-		transfer_list_fini(&instance->transfers_control_full); \
-		transfer_list_fini(&instance->transfers_control_slow); \
-		transfer_list_fini(&instance->transfers_interrupt); \
-		return ret; \
-	} \
-} while (0)
-
-	SETUP_TRANSFER_LIST(bulk_full, "BULK FULL");
-	SETUP_TRANSFER_LIST(control_full, "CONTROL FULL");
-	SETUP_TRANSFER_LIST(control_slow, "CONTROL LOW");
-	SETUP_TRANSFER_LIST(interrupt, "INTERRUPT");
-#undef SETUP_TRANSFER_LIST
-	/* Connect lists into one schedule */
-	transfer_list_set_next(&instance->transfers_control_full,
-		&instance->transfers_bulk_full);
-	transfer_list_set_next(&instance->transfers_control_slow,
-		&instance->transfers_control_full);
-	transfer_list_set_next(&instance->transfers_interrupt,
-		&instance->transfers_control_slow);
-
-	/*FSBR, This feature is not needed (adds no benefit) and is supposedly
-	 * buggy on certain hw, enable at your own risk. */
-#ifdef FSBR
-	transfer_list_set_next(&instance->transfers_bulk_full,
-	    &instance->transfers_control_full);
-#endif
-
-	/* Assign pointers to be used during scheduling */
-	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
-	  &instance->transfers_interrupt;
-	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
-	  &instance->transfers_interrupt;
-	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
-	  &instance->transfers_control_full;
-	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
-	  &instance->transfers_control_slow;
-	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
-	  &instance->transfers_bulk_full;
-
-	return EOK;
-#undef CHECK_RET_CLEAR_RETURN
-}
-/*----------------------------------------------------------------------------*/
-/** Schedule batch for execution.
- *
- * @param[in] instance UHCI structure to use.
- * @param[in] batch Transfer batch to schedule.
- * @return Error code
- *
- * Checks for bandwidth availability and appends the batch to the proper queue.
- */
-int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
-{
-	assert(instance);
-	assert(batch);
-
-	transfer_list_t *list =
-	    instance->transfers[batch->ep->speed][batch->ep->transfer_type];
-	assert(list);
-	transfer_list_add_batch(list, batch);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Take action based on the interrupt cause.
- *
- * @param[in] instance UHCI structure to use.
- * @param[in] status Value of the status register at the time of interrupt.
- *
- * Interrupt might indicate:
- * - transaction completed, either by triggering IOC, SPD, or an error
- * - some kind of device error
- * - resume from suspend state (not implemented)
- */
-void hc_interrupt(hc_t *instance, uint16_t status)
-{
-	assert(instance);
-	/* Lower 2 bits are transaction error and transaction complete */
-	if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
-		LIST_INITIALIZE(done);
-		transfer_list_remove_finished(
-		    &instance->transfers_interrupt, &done);
-		transfer_list_remove_finished(
-		    &instance->transfers_control_slow, &done);
-		transfer_list_remove_finished(
-		    &instance->transfers_control_full, &done);
-		transfer_list_remove_finished(
-		    &instance->transfers_bulk_full, &done);
-
-		while (!list_empty(&done)) {
-			link_t *item = done.next;
-			list_remove(item);
-			usb_transfer_batch_t *batch =
-			    list_get_instance(item, usb_transfer_batch_t, link);
-			usb_transfer_batch_finish(batch);
-		}
-	}
-	/* Resume interrupts are not supported */
-	if (status & UHCI_STATUS_RESUME) {
-		usb_log_error("Resume interrupt!\n");
-	}
-
-	/* Bits 4 and 5 indicate hc error */
-	if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
-		usb_log_error("UHCI hardware failure!.\n");
-		++instance->hw_failures;
-		transfer_list_abort_all(&instance->transfers_interrupt);
-		transfer_list_abort_all(&instance->transfers_control_slow);
-		transfer_list_abort_all(&instance->transfers_control_full);
-		transfer_list_abort_all(&instance->transfers_bulk_full);
-
-		if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
-			/* reinitialize hw, this triggers virtual disconnect*/
-			hc_init_hw(instance);
-		} else {
-			usb_log_fatal("Too many UHCI hardware failures!.\n");
-			hc_fini(instance);
-		}
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** Polling function, emulates interrupts.
- *
- * @param[in] arg UHCI hc structure to use.
- * @return EOK (should never return)
- */
-int hc_interrupt_emulator(void* arg)
-{
-	usb_log_debug("Started interrupt emulator.\n");
-	hc_t *instance = arg;
-	assert(instance);
-
-	while (1) {
-		/* Read and clear status register */
-		uint16_t status = pio_read_16(&instance->registers->usbsts);
-		pio_write_16(&instance->registers->usbsts, status);
-		if (status != 0)
-			usb_log_debug2("UHCI status: %x.\n", status);
-// Qemu fails to report stalled communication
-// see https://bugs.launchpad.net/qemu/+bug/757654
-// This is a simple workaround to force queue processing every time
-	//	status |= 1;
-		hc_interrupt(instance, status);
-		async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
-	}
-	return EOK;
-}
-/*---------------------------------------------------------------------------*/
-/** Debug function, checks consistency of memory structures.
- *
- * @param[in] arg UHCI structure to use.
- * @return EOK (should never return)
- */
-int hc_debug_checker(void *arg)
-{
-	hc_t *instance = arg;
-	assert(instance);
-
-#define QH(queue) \
-	instance->transfers_##queue.queue_head
-
-	while (1) {
-		const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
-		const uint16_t sts = pio_read_16(&instance->registers->usbsts);
-		const uint16_t intr =
-		    pio_read_16(&instance->registers->usbintr);
-
-		if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
-			usb_log_debug2("Command: %X Status: %X Intr: %x\n",
-			    cmd, sts, intr);
-		}
-
-		const uintptr_t frame_list =
-		    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
-		if (frame_list != addr_to_phys(instance->frame_list)) {
-			usb_log_debug("Framelist address: %p vs. %p.\n",
-			    (void *) frame_list,
-			    (void *) addr_to_phys(instance->frame_list));
-		}
-
-		int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
-
-		uintptr_t expected_pa = instance->frame_list[frnum]
-		    & LINK_POINTER_ADDRESS_MASK;
-		uintptr_t real_pa = addr_to_phys(QH(interrupt));
-		if (expected_pa != real_pa) {
-			usb_log_debug("Interrupt QH: %p (frame %d) vs. %p.\n",
-			    (void *) expected_pa, frnum, (void *) real_pa);
-		}
-
-		expected_pa = QH(interrupt)->next & LINK_POINTER_ADDRESS_MASK;
-		real_pa = addr_to_phys(QH(control_slow));
-		if (expected_pa != real_pa) {
-			usb_log_debug("Control Slow QH: %p vs. %p.\n",
-			    (void *) expected_pa, (void *) real_pa);
-		}
-
-		expected_pa = QH(control_slow)->next & LINK_POINTER_ADDRESS_MASK;
-		real_pa = addr_to_phys(QH(control_full));
-		if (expected_pa != real_pa) {
-			usb_log_debug("Control Full QH: %p vs. %p.\n",
-			    (void *) expected_pa, (void *) real_pa);
-		}
-
-		expected_pa = QH(control_full)->next & LINK_POINTER_ADDRESS_MASK;
-		real_pa = addr_to_phys(QH(bulk_full));
-		if (expected_pa != real_pa ) {
-			usb_log_debug("Bulk QH: %p vs. %p.\n",
-			    (void *) expected_pa, (void *) real_pa);
-		}
-		async_usleep(UHCI_DEBUGER_TIMEOUT);
-	}
-	return EOK;
-#undef QH
-}
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/hc.h
===================================================================
--- uspace/drv/uhci_hcd/hc.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,160 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI host controller driver structure
- */
-#ifndef DRV_UHCI_HC_H
-#define DRV_UHCI_HC_H
-
-#include <fibril.h>
-#include <ddi.h>
-
-#include <usb/host/device_keeper.h>
-#include <usb/host/usb_endpoint_manager.h>
-#include <usb/host/batch.h>
-
-#include "transfer_list.h"
-
-/** UHCI I/O registers layout */
-typedef struct uhci_regs {
-	/** Command register, controls HC behaviour */
-	uint16_t usbcmd;
-#define UHCI_CMD_MAX_PACKET (1 << 7)
-#define UHCI_CMD_CONFIGURE  (1 << 6)
-#define UHCI_CMD_DEBUG  (1 << 5)
-#define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
-#define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
-#define UHCI_CMD_GLOBAL_RESET  (1 << 2)
-#define UHCI_CMD_HCRESET  (1 << 1)
-#define UHCI_CMD_RUN_STOP  (1 << 0)
-
-	/** Status register, 1 means interrupt is asserted (if enabled) */
-	uint16_t usbsts;
-#define UHCI_STATUS_HALTED (1 << 5)
-#define UHCI_STATUS_PROCESS_ERROR (1 << 4)
-#define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
-#define UHCI_STATUS_RESUME (1 << 2)
-#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
-#define UHCI_STATUS_INTERRUPT (1 << 0)
-#define UHCI_STATUS_NM_INTERRUPTS \
-    (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)
-
-	/** Interrupt enabled registers */
-	uint16_t usbintr;
-#define UHCI_INTR_SHORT_PACKET (1 << 3)
-#define UHCI_INTR_COMPLETE (1 << 2)
-#define UHCI_INTR_RESUME (1 << 1)
-#define UHCI_INTR_CRC (1 << 0)
-
-	/** Register stores frame number used in SOF packet */
-	uint16_t frnum;
-
-	/** Pointer(physical) to the Frame List */
-	uint32_t flbaseadd;
-
-	/** SOF modification to match external timers */
-	uint8_t sofmod;
-} regs_t;
-
-#define UHCI_FRAME_LIST_COUNT 1024
-#define UHCI_INT_EMULATOR_TIMEOUT 10000
-#define UHCI_DEBUGER_TIMEOUT 5000000
-#define UHCI_ALLOWED_HW_FAIL 5
-#define UHCI_NEEDED_IRQ_COMMANDS 5
-
-/** Main UHCI driver structure */
-typedef struct hc {
-	/** USB bus driver, devices and addresses */
-	usb_device_keeper_t manager;
-	/** USB bus driver, endpoints */
-	usb_endpoint_manager_t ep_manager;
-
-	/** Addresses of I/O registers */
-	regs_t *registers;
-
-	/** Frame List contains 1024 link pointers */
-	link_pointer_t *frame_list;
-
-	/** List and queue of interrupt transfers */
-	transfer_list_t transfers_interrupt;
-	/** List and queue of low speed control transfers */
-	transfer_list_t transfers_control_slow;
-	/** List and queue of full speed bulk transfers */
-	transfer_list_t transfers_bulk_full;
-	/** List and queue of full speed control transfers */
-	transfer_list_t transfers_control_full;
-
-	/** Pointer table to the above lists, helps during scheduling */
-	transfer_list_t *transfers[2][4];
-
-	/** Code to be executed in kernel interrupt handler */
-	irq_code_t interrupt_code;
-
-	/** Commands that form interrupt code */
-	irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS];
-
-	/** Fibril periodically checking status register*/
-	fid_t interrupt_emulator;
-
-	/** Indicator of hw interrupts availability */
-	bool hw_interrupts;
-
-	/** Number of hw failures detected. */
-	unsigned hw_failures;
-} hc_t;
-
-int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
-
-int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
-
-void hc_interrupt(hc_t *instance, uint16_t status);
-
-/** Safely dispose host controller internal structures
- *
- * @param[in] instance Host controller structure to use.
- */
-static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
-
-/** Get and cast pointer to the driver data
- *
- * @param[in] fun DDF function pointer
- * @return cast pointer to driver_data
- */
-static inline hc_t * fun_to_hc(ddf_fun_t *fun)
-{
-	assert(fun);
-	return fun->driver_data;
-}
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/hw_struct/link_pointer.h
===================================================================
--- uspace/drv/uhci_hcd/hw_struct/link_pointer.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,61 +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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_HW_STRUCT_LINK_POINTER_H
-#define DRV_UHCI_HW_STRUCT_LINK_POINTER_H
-
-/* UHCI link pointer, used by many data structures */
-typedef uint32_t link_pointer_t;
-
-#define LINK_POINTER_TERMINATE_FLAG (1 << 0)
-#define LINK_POINTER_QUEUE_HEAD_FLAG (1 << 1)
-#define LINK_POINTER_ZERO_BIT_FLAG (1 << 2)
-#define LINK_POINTER_VERTICAL_FLAG (1 << 2)
-#define LINK_POINTER_RESERVED_FLAG (1 << 3)
-
-#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
-
-#define LINK_POINTER_QH(address) \
-	((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG)
-
-#define LINK_POINTER_TD(address) \
-	(address & LINK_POINTER_ADDRESS_MASK)
-
-#define LINK_POINTER_TERM \
-	((link_pointer_t)LINK_POINTER_TERMINATE_FLAG)
-
-#endif
-/**
- * @}
- */
-
Index: pace/drv/uhci_hcd/hw_struct/queue_head.h
===================================================================
--- uspace/drv/uhci_hcd/hw_struct/queue_head.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,100 +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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_HW_STRUCT_QH_H
-#define DRV_UHCI_HW_STRUCT_QH_H
-#include <assert.h>
-
-#include "link_pointer.h"
-#include "transfer_descriptor.h"
-#include "../utils/malloc32.h"
-
-/** This structure is defined in UHCI design guide p. 31 */
-typedef struct queue_head {
-	/** Pointer to the next entity (another QH or TD */
-	volatile link_pointer_t next;
-	/** Pointer to the contained entities (execution controlled by vertical flag*/
-	volatile link_pointer_t element;
-} __attribute__((packed)) qh_t;
-/*----------------------------------------------------------------------------*/
-/** Initialize queue head structure
- *
- * @param[in] instance qh_t structure to initialize.
- *
- * Sets both pointer to terminal NULL.
- */
-static inline void qh_init(qh_t *instance)
-{
-	assert(instance);
-
-	instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
-	instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
-}
-/*----------------------------------------------------------------------------*/
-/** Set queue head next pointer
- *
- * @param[in] instance qh_t structure to use.
- * @param[in] next Address of the next queue.
- *
- * Adds proper flag. If the pointer is NULL, sets next to terminal NULL.
- */
-static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
-{
-	uint32_t pa = addr_to_phys(next);
-	if (pa) {
-		instance->next = LINK_POINTER_QH(pa);
-	} else {
-		instance->next = LINK_POINTER_TERM;
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** Set queue head element pointer
- *
- * @param[in] instance qh_t structure to use.
- * @param[in] td Transfer descriptor to set as the first element.
- *
- * Adds proper flag. If the pointer is NULL, sets element to terminal NULL.
- */
-static inline void qh_set_element_td(qh_t *instance, td_t *td)
-{
-	uint32_t pa = addr_to_phys(td);
-	if (pa) {
-		instance->element = LINK_POINTER_TD(pa);
-	} else {
-		instance->element = LINK_POINTER_TERM;
-	}
-}
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci_hcd/hw_struct/transfer_descriptor.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,176 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#include <errno.h>
-#include <usb/debug.h>
-
-#include "transfer_descriptor.h"
-#include "../utils/malloc32.h"
-
-/** Initialize Transfer Descriptor
- *
- * @param[in] instance Memory place to initialize.
- * @param[in] err_count Number of retries hc should attempt.
- * @param[in] size Size of data source.
- * @param[in] toggle Value of toggle bit.
- * @param[in] iso True if TD represents Isochronous transfer.
- * @param[in] low_speed Target device's speed.
- * @param[in] target Address and endpoint receiving the transfer.
- * @param[in] pid Packet identification (SETUP, IN or OUT).
- * @param[in] buffer Source of data.
- * @param[in] next Net TD in transaction.
- * @return Error code.
- *
- * Uses a mix of supplied and default values.
- * Implicit values:
- *  - all TDs have vertical flag set (makes transfers to endpoints atomic)
- *  - in the error field only active it is set
- *  - if the packet uses PID_IN and is not isochronous SPD is set
- *
- * Dumps 8 bytes of buffer if PID_SETUP is used.
- */
-void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
-    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
-    td_t *next)
-{
-	assert(instance);
-	assert(size < 1024);
-	assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
-	    || (pid == USB_PID_OUT));
-
-	const uint32_t next_pa = addr_to_phys(next);
-	assert((next_pa & LINK_POINTER_ADDRESS_MASK) == next_pa);
-
-	instance->next = 0
-	    | LINK_POINTER_VERTICAL_FLAG
-	    | (next_pa ? next_pa : LINK_POINTER_TERMINATE_FLAG);
-
-	instance->status = 0
-	    | ((err_count & TD_STATUS_ERROR_COUNT_MASK)
-	        << TD_STATUS_ERROR_COUNT_POS)
-	    | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
-	    | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
-	    | TD_STATUS_ERROR_ACTIVE;
-
-	if (pid == USB_PID_IN && !iso) {
-		instance->status |= TD_STATUS_SPD_FLAG;
-	}
-
-	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)
-	    | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
-
-	instance->buffer_ptr = addr_to_phys(buffer);
-
-	usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
-	    instance, instance->next, instance->status, instance->device,
-	    instance->buffer_ptr, buffer);
-	td_print_status(instance);
-	if (pid == USB_PID_SETUP) {
-		usb_log_debug("SETUP BUFFER: %s\n",
-		    usb_debug_str_buffer(buffer, 8, 8));
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** Convert TD status into standard error code
- *
- * @param[in] instance TD structure to use.
- * @return Error code.
- */
-int td_status(td_t *instance)
-{
-	assert(instance);
-
-	/* This is hc internal error it should never be reported. */
-	if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
-		return EAGAIN;
-
-	/* CRC or timeout error, like device not present or bad data,
-	 * it won't be reported unless err count reached zero */
-	if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
-		return EBADCHECKSUM;
-
-	/* HC does not end transactions on these, it should never be reported */
-	if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
-		return EAGAIN;
-
-	/* Buffer overrun or underrun */
-	if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
-		return ERANGE;
-
-	/* Device babble is something serious */
-	if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
-		return EIO;
-
-	/* Stall might represent err count reaching zero or stall response from
-	 * the device. If err count reached zero, one of the above is reported*/
-	if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
-		return ESTALL;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Print values in status field (dw1) in a human readable way.
- *
- * @param[in] instance TD structure to use.
- */
-void td_print_status(td_t *instance)
-{
-	assert(instance);
-	const uint32_t s = instance->status;
-	usb_log_debug2("TD(%p) status(%#" PRIx32 "):%s %d,%s%s%s%s%s%s%s%s%s%s%s %zu.\n",
-	    instance, instance->status,
-	    (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
-	    (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK,
-	    (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "",
-	    (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "",
-	    (s & TD_STATUS_IOC_FLAG) ? " IOC," : "",
-	    (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "",
-	    (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "",
-	    (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "",
-	    (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "",
-	    (s & TD_STATUS_ERROR_NAK) ? " NAK," : "",
-	    (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "",
-	    (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
-	    (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
-	    td_act_size(instance)
-	);
-}
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci_hcd/hw_struct/transfer_descriptor.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,166 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
-#define DRV_UHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
-
-#include <mem.h>
-#include <usb/usb.h>
-
-#include "link_pointer.h"
-
-/** Transfer Descriptor, defined in UHCI design guide p. 26 */
-typedef struct transfer_descriptor {
-	/** Pointer to the next entity (TD or QH) */
-	link_pointer_t next;
-
-	/** Status doubleword */
-	volatile uint32_t status;
-#define TD_STATUS_RESERVED_MASK 0xc000f800
-#define TD_STATUS_SPD_FLAG         (1 << 29)
-#define TD_STATUS_ERROR_COUNT_POS 27
-#define TD_STATUS_ERROR_COUNT_MASK 0x3
-#define TD_STATUS_LOW_SPEED_FLAG   (1 << 26)
-#define TD_STATUS_ISOCHRONOUS_FLAG (1 << 25)
-#define TD_STATUS_IOC_FLAG         (1 << 24)
-
-#define TD_STATUS_ERROR_ACTIVE    (1 << 23)
-#define TD_STATUS_ERROR_STALLED   (1 << 22)
-#define TD_STATUS_ERROR_BUFFER    (1 << 21)
-#define TD_STATUS_ERROR_BABBLE    (1 << 20)
-#define TD_STATUS_ERROR_NAK       (1 << 19)
-#define TD_STATUS_ERROR_CRC       (1 << 18)
-#define TD_STATUS_ERROR_BIT_STUFF (1 << 17)
-#define TD_STATUS_ERROR_RESERVED  (1 << 16)
-#define TD_STATUS_ERROR_POS 16
-#define TD_STATUS_ERROR_MASK 0xff
-
-#define TD_STATUS_ACTLEN_POS 0
-#define TD_STATUS_ACTLEN_MASK 0x7ff
-
-	/* double word with USB device specific info */
-	volatile uint32_t device;
-#define TD_DEVICE_MAXLEN_POS 21
-#define TD_DEVICE_MAXLEN_MASK 0x7ff
-#define TD_DEVICE_RESERVED_FLAG        (1 << 20)
-#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG (1 << 19)
-#define TD_DEVICE_ENDPOINT_POS 15
-#define TD_DEVICE_ENDPOINT_MASK 0xf
-#define TD_DEVICE_ADDRESS_POS 8
-#define TD_DEVICE_ADDRESS_MASK 0x7f
-#define TD_DEVICE_PID_POS 0
-#define TD_DEVICE_PID_MASK 0xff
-
-	/** Pointer(physical) to the beginning of the transaction's buffer */
-	volatile uint32_t buffer_ptr;
-
-	/* According to UHCI design guide, there is 16 bytes of
-	 * data available here.
-	 * According to linux kernel the hardware does not care,
-	 * it just needs to be aligned. We don't use it anyway.
-	 */
-} __attribute__((packed)) td_t;
-
-
-void td_init(td_t *instance, int error_count, size_t size, bool toggle,
-    bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
-    void *buffer, td_t *next);
-
-int td_status(td_t *instance);
-
-void td_print_status(td_t *instance);
-/*----------------------------------------------------------------------------*/
-/** Helper function for parsing actual size out of TD.
- *
- * @param[in] instance TD structure to use.
- * @return Parsed actual size.
- */
-static inline size_t td_act_size(td_t *instance)
-{
-	assert(instance);
-	const uint32_t s = instance->status;
-	return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
-}
-/*----------------------------------------------------------------------------*/
-/** Check whether less than max data were received on SPD marked transfer.
- *
- * @param[in] instance TD structure to use.
- * @return True if data packet is short (less than max bytes and SPD set),
- * false otherwise.
- */
-static inline bool td_is_short(td_t *instance)
-{
-	const size_t act_size = td_act_size(instance);
-	const size_t max_size =
-	    ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1)
-	    & TD_DEVICE_MAXLEN_MASK;
-	return
-	    (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function for parsing value of toggle bit.
- *
- * @param[in] instance TD structure to use.
- * @return Toggle bit value.
- */
-static inline int td_toggle(td_t *instance)
-{
-	assert(instance);
-	return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function for parsing value of active bit
- *
- * @param[in] instance TD structure to use.
- * @return Active bit value.
- */
-static inline bool td_is_active(td_t *instance)
-{
-	assert(instance);
-	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
-}
-/*----------------------------------------------------------------------------*/
-/** Helper function for setting IOC bit.
- *
- * @param[in] instance TD structure to use.
- */
-static inline void td_set_ioc(td_t *instance)
-{
-	assert(instance);
-	instance->status |= TD_STATUS_IOC_FLAG;
-}
-/*----------------------------------------------------------------------------*/
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/iface.c
===================================================================
--- uspace/drv/uhci_hcd/iface.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,404 +1,0 @@
-/*
- * Copyright (c) 2011 Vojtech Horky, Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver hc interface implementation
- */
-#include <ddf/driver.h>
-#include <errno.h>
-
-#include <usb/debug.h>
-#include <usb/host/endpoint.h>
-
-#include "iface.h"
-#include "batch.h"
-#include "hc.h"
-
-static inline int setup_batch(
-    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
-    void *data, size_t size, void * setup_data, size_t setup_size,
-    usbhc_iface_transfer_in_callback_t in,
-    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
-    hc_t **hc, usb_transfer_batch_t **batch)
-{
-	assert(hc);
-	assert(batch);
-	assert(fun);
-	*hc = fun_to_hc(fun);
-	assert(*hc);
-
-	size_t res_bw;
-	endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
-	    target.address, target.endpoint, direction, &res_bw);
-	if (ep == NULL) {
-		usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
-		    target.address, target.endpoint, name);
-		return ENOENT;
-	}
-
-	usb_log_debug("%s %d:%d %zu(%zu).\n",
-	    name, target.address, target.endpoint, size, ep->max_packet_size);
-
-	const size_t bw = bandwidth_count_usb11(
-	    ep->speed, ep->transfer_type, size, ep->max_packet_size);
-	if (res_bw < bw) {
-		usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
-		    "but only %zu is reserved.\n",
-		    target.address, target.endpoint, name, bw, res_bw);
-		return ENOSPC;
-	}
-
-	*batch = batch_get(
-	        fun, ep, data, size, setup_data, setup_size, in, out, arg);
-	if (!*batch)
-		return ENOMEM;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Request address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] speed Speed to associate with the new default address.
- * @param[out] address Place to write a new address.
- * @return Error code.
- */
-static int request_address(
-    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	assert(address);
-
-	usb_log_debug("Address request with speed %d.\n", speed);
-	*address = device_keeper_get_free_address(&hc->manager, speed);
-	usb_log_debug("Address request with result: %d.\n", *address);
-	if (*address <= 0)
-		return *address;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Bind address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address Address of the device
- * @param[in] handle Devman handle of the device driver.
- * @return Error code.
- */
-static int bind_address(
-  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
-	usb_device_keeper_bind(&hc->manager, address, handle);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Find device handle by address interface function.
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address Address in question.
- * @param[out] handle Where to store device handle if found.
- * @return Error code.
- */
-static int find_by_address(ddf_fun_t *fun, usb_address_t address,
-    devman_handle_t *handle)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	const bool found =
-	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
-	return found ? EOK : ENOENT;
-}
-/*----------------------------------------------------------------------------*/
-/** Release address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address USB address to be released.
- * @return Error code.
- */
-static int release_address(ddf_fun_t *fun, usb_address_t address)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	usb_log_debug("Address release %d.\n", address);
-	usb_device_keeper_release(&hc->manager, address);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int register_endpoint(
-    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
-    usb_endpoint_t endpoint,
-    usb_transfer_type_t transfer_type, usb_direction_t direction,
-    size_t max_packet_size, unsigned int interval)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	const size_t size = max_packet_size;
-	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
-	if (speed >= USB_SPEED_MAX) {
-		speed = ep_speed;
-	}
-	usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
-	    address, endpoint, usb_str_transfer_type(transfer_type),
-	    usb_str_speed(speed), direction, size, max_packet_size, interval);
-
-	return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
-	    direction, transfer_type, speed, max_packet_size, size);
-}
-/*----------------------------------------------------------------------------*/
-static int unregister_endpoint(
-    ddf_fun_t *fun, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction)
-{
-	assert(fun);
-	hc_t *hc = fun_to_hc(fun);
-	assert(hc);
-	usb_log_debug("Unregister endpoint %d:%d %d.\n",
-	    address, endpoint, direction);
-	return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
-	    endpoint, direction);
-}
-/*----------------------------------------------------------------------------*/
-/** Interrupt out transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] data Source of data.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion
- * @param[in] arg Additional for callback function.
- * @return Error code.
- */
-static int interrupt_out(
-    ddf_fun_t *fun, usb_target_t target, void *data,
-    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
-	    NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	assert(batch);
-	assert(hc);
-	batch_interrupt_out(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Interrupt in transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[out] data Data destination.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion
- * @param[in] arg Additional for callback function.
- * @return Error code.
- */
-static int interrupt_in(
-    ddf_fun_t *fun, usb_target_t target, void *data,
-    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
-	    NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	assert(batch);
-	assert(hc);
-	batch_interrupt_in(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Bulk out transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] data Source of data.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion
- * @param[in] arg Additional for callback function.
- * @return Error code.
- */
-static int bulk_out(
-    ddf_fun_t *fun, usb_target_t target, void *data,
-    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
-	    NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	assert(batch);
-	assert(hc);
-	batch_bulk_out(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Bulk in transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[out] data Data destination.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion
- * @param[in] arg Additional for callback function.
- * @return Error code.
- */
-static int bulk_in(
-    ddf_fun_t *fun, usb_target_t target, void *data,
-    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
-	    NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	assert(batch);
-	assert(hc);
-	batch_bulk_in(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Control write transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] setup_data Data to send with SETUP transfer.
- * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
- * @param[in] data Source of data.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion.
- * @param[in] arg Additional for callback function.
- * @return Error code.
- */
-static int control_write(
-    ddf_fun_t *fun, 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)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
-	    setup_data, setup_size, NULL, callback, arg, "Control WRITE",
-	    &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	assert(batch);
-	assert(hc);
-	usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
-	batch_control_write(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Control read transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] setup_data Data to send with SETUP packet.
- * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
- * @param[out] data Source of data.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion.
- * @param[in] arg Additional for callback function.
- * @return Error code.
- */
-static int control_read(
-    ddf_fun_t *fun, 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)
-{
-	usb_transfer_batch_t *batch = NULL;
-	hc_t *hc = NULL;
-	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
-	    setup_data, setup_size, callback, NULL, arg, "Control READ",
-	    &hc, &batch);
-	if (ret != EOK)
-		return ret;
-	assert(batch);
-	assert(hc);
-	batch_control_read(batch);
-	ret = hc_schedule(hc, batch);
-	if (ret != EOK) {
-		usb_transfer_batch_dispose(batch);
-	}
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-usbhc_iface_t hc_iface = {
-	.request_address = request_address,
-	.bind_address = bind_address,
-	.find_by_address = find_by_address,
-	.release_address = release_address,
-
-	.register_endpoint = register_endpoint,
-	.unregister_endpoint = unregister_endpoint,
-
-	.interrupt_out = interrupt_out,
-	.interrupt_in = interrupt_in,
-
-	.bulk_out = bulk_out,
-	.bulk_in = bulk_in,
-
-	.control_write = control_write,
-	.control_read = control_read,
-};
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/iface.h
===================================================================
--- uspace/drv/uhci_hcd/iface.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,45 +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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver iface
- */
-#ifndef DRV_UHCI_IFACE_H
-#define DRV_UHCI_IFACE_H
-
-#include <usbhc_iface.h>
-
-extern usbhc_iface_t hc_iface;
-
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/main.c
===================================================================
--- uspace/drv/uhci_hcd/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,94 +1,0 @@
-/*
- * Copyright (c) 2011 Vojtech Horky, Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver initialization
- */
-#include <ddf/driver.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/ddfiface.h>
-#include <usb/debug.h>
-
-#include "uhci.h"
-
-#define NAME "uhci_hcd"
-
-static int uhci_add_device(ddf_dev_t *device);
-/*----------------------------------------------------------------------------*/
-static driver_ops_t uhci_driver_ops = {
-	.add_device = uhci_add_device,
-};
-/*----------------------------------------------------------------------------*/
-static driver_t uhci_driver = {
-	.name = NAME,
-	.driver_ops = &uhci_driver_ops
-};
-/*----------------------------------------------------------------------------*/
-/** Initialize a new ddf driver instance for uhci hc and hub.
- *
- * @param[in] device DDF instance of the device to initialize.
- * @return Error code.
- */
-int uhci_add_device(ddf_dev_t *device)
-{
-	usb_log_debug2("uhci_add_device() called\n");
-	assert(device);
-
-	int ret = device_setup_uhci(device);
-	if (ret != EOK) {
-		usb_log_error("Failed to initialize UHCI driver: %s.\n",
-		    str_error(ret));
-		return ret;
-	}
-	usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize global driver structures (NONE).
- *
- * @param[in] argc Number of arguments in argv vector (ignored).
- * @param[in] argv Cmdline argument vector (ignored).
- * @return Error code.
- *
- * Driver debug level is set here.
- */
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS UHCI driver.\n");
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-
-	return ddf_driver_main(&uhci_driver);
-}
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/pci.c
===================================================================
--- uspace/drv/uhci_hcd/pci.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,169 +1,0 @@
-/*
- * 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 drvusbuhcihc
- * @{
- */
-/**
- * @file
- * PCI related functions needed by the UHCI driver.
- */
-
-#include <errno.h>
-#include <assert.h>
-#include <devman.h>
-#include <device/hw_res.h>
-
-#include <usb/debug.h>
-#include <pci_dev_iface.h>
-
-#include "pci.h"
-
-/** Get I/O address of registers and IRQ for given device.
- *
- * @param[in] dev Device asking for the addresses.
- * @param[out] io_reg_address Base address of the I/O range.
- * @param[out] io_reg_size Size of the I/O range.
- * @param[out] irq_no IRQ assigned to the device.
- * @return Error code.
- */
-int pci_get_my_registers(const ddf_dev_t *dev,
-    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
-{
-	assert(dev);
-	assert(io_reg_address);
-	assert(io_reg_size);
-	assert(irq_no);
-	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	hw_resource_list_t hw_resources;
-	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
-	if (rc != EOK) {
-		async_hangup(parent_sess);
-		return rc;
-	}
-	
-	uintptr_t io_address = 0;
-	size_t io_size = 0;
-	bool io_found = false;
-	
-	int irq = 0;
-	bool irq_found = false;
-	
-	size_t i;
-	for (i = 0; i < hw_resources.count; i++) {
-		const hw_resource_t *res = &hw_resources.resources[i];
-		switch (res->type) {
-		case INTERRUPT:
-			irq = res->res.interrupt.irq;
-			irq_found = true;
-			usb_log_debug2("Found interrupt: %d.\n", irq);
-			break;
-		case IO_RANGE:
-			io_address = res->res.io_range.address;
-			io_size = res->res.io_range.size;
-			usb_log_debug2("Found io: %" PRIx64" %zu.\n",
-			    res->res.io_range.address, res->res.io_range.size);
-			io_found = true;
-			break;
-		default:
-			break;
-		}
-	}
-	
-	async_hangup(parent_sess);
-	
-	if (!io_found || !irq_found)
-		return ENOENT;
-	
-	*io_reg_address = io_address;
-	*io_reg_size = io_size;
-	*irq_no = irq;
-	
-	return EOK;
-}
-
-/** Call the PCI driver with a request to enable interrupts
- *
- * @param[in] device Device asking for interrupts
- * @return Error code.
- */
-int pci_enable_interrupts(const ddf_dev_t *device)
-{
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	const bool enabled = hw_res_enable_interrupt(parent_sess);
-	async_hangup(parent_sess);
-	
-	return enabled ? EOK : EIO;
-}
-
-/** Call the PCI driver with a request to clear legacy support register
- *
- * @param[in] device Device asking to disable interrupts
- * @return Error code.
- */
-int pci_disable_legacy(const ddf_dev_t *device)
-{
-	assert(device);
-	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	/* See UHCI design guide for these values p.45,
-	 * write all WC bits in USB legacy register */
-	const sysarg_t address = 0xc0;
-	const sysarg_t value = 0xaf00;
-	
-	async_exch_t *exch = async_exchange_begin(parent_sess);
-	
-	const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE),
-	    IPC_M_CONFIG_SPACE_WRITE_16, address, value);
-	
-	async_exchange_end(exch);
-	async_hangup(parent_sess);
-	
-	return rc;
-}
-
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/pci.h
===================================================================
--- uspace/drv/uhci_hcd/pci.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,48 +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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver PCI helper functions
- */
-#ifndef DRV_UHCI_PCI_H
-#define DRV_UHCI_PCI_H
-
-#include <ddf/driver.h>
-
-int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
-int pci_enable_interrupts(const ddf_dev_t *);
-int pci_disable_legacy(const ddf_dev_t *);
-
-#endif
-/**
- * @}
- */
-
Index: pace/drv/uhci_hcd/root_hub.c
===================================================================
--- uspace/drv/uhci_hcd/root_hub.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,85 +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 drvusbuhci
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#include <assert.h>
-#include <errno.h>
-#include <str_error.h>
-#include <stdio.h>
-
-#include <usb/debug.h>
-
-#include "root_hub.h"
-
-/** Root hub initialization
- * @param[in] instance RH structure to initialize
- * @param[in] fun DDF function representing UHCI root hub
- * @param[in] reg_addr Address of root hub status and control registers.
- * @param[in] reg_size Size of accessible address space.
- * @return Error code.
- */
-int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
-{
-	assert(fun);
-
-	char *match_str = NULL;
-	int ret = asprintf(&match_str, "usb&uhci&root-hub");
-	if (ret < 0) {
-		usb_log_error(
-		    "Failed(%d) to create root hub match string: %s.\n",
-		    ret, str_error(ret));
-		return ret;
-	}
-	assert(match_str);
-
-	ret = ddf_fun_add_match_id(fun, match_str, 100);
-	if (ret != EOK) {
-		free(match_str);
-		usb_log_error("Failed(%d) to add root hub match id: %s\n",
-		    ret, str_error(ret));
-		return ret;
-	}
-
-	/* Initialize resource structure */
-	instance->resource_list.count = 1;
-	instance->resource_list.resources = &instance->io_regs;
-
-	instance->io_regs.type = IO_RANGE;
-	instance->io_regs.res.io_range.address = reg_addr;
-	instance->io_regs.res.io_range.size = reg_size;
-	instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
-
-	return EOK;
-}
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/root_hub.h
===================================================================
--- uspace/drv/uhci_hcd/root_hub.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,55 +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 drvusbuhci
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_RH_H
-#define DRV_UHCI_RH_H
-
-#include <ddf/driver.h>
-#include <ops/hw_res.h>
-
-/** DDF support structure for uhci_rhd driver, provides I/O resources */
-typedef struct rh {
-	/** List of resources available to the root hub. */
-	hw_resource_list_t resource_list;
-	/** The only resource in the RH resource list */
-	hw_resource_t io_regs;
-} rh_t;
-
-int rh_init(
-    rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size);
-
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci_hcd/transfer_list.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,241 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver transfer list implementation
- */
-#include <errno.h>
-#include <usb/debug.h>
-#include <arch/barrier.h>
-
-
-#include "transfer_list.h"
-#include "batch.h"
-
-static void transfer_list_remove_batch(
-    transfer_list_t *instance, usb_transfer_batch_t *batch);
-/*----------------------------------------------------------------------------*/
-/** Initialize transfer list structures.
- *
- * @param[in] instance Memory place to use.
- * @param[in] name Name of the new list.
- * @return Error code
- *
- * Allocates memory for internal qh_t structure.
- */
-int transfer_list_init(transfer_list_t *instance, const char *name)
-{
-	assert(instance);
-	instance->name = name;
-	instance->queue_head = malloc32(sizeof(qh_t));
-	if (!instance->queue_head) {
-		usb_log_error("Failed to allocate queue head.\n");
-		return ENOMEM;
-	}
-	const uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
-	usb_log_debug2("Transfer list %s setup with QH: %p (%#" PRIx32" ).\n",
-	    name, instance->queue_head, queue_head_pa);
-
-	qh_init(instance->queue_head);
-	list_initialize(&instance->batch_list);
-	fibril_mutex_initialize(&instance->guard);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Dispose transfer list structures.
- *
- * @param[in] instance Memory place to use.
- *
- * Frees memory of the internal qh_t structure.
- */
-void transfer_list_fini(transfer_list_t *instance)
-{
-	assert(instance);
-	free32(instance->queue_head);
-}
-/** Set the next list in transfer list chain.
- *
- * @param[in] instance List to lead.
- * @param[in] next List to append.
- * @return Error code
- *
- * Does not check whether this replaces an existing list .
- */
-void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
-{
-	assert(instance);
-	assert(instance->queue_head);
-	assert(next);
-	/* Set queue_head.next to point to the follower */
-	qh_set_next_qh(instance->queue_head, next->queue_head);
-}
-/*----------------------------------------------------------------------------*/
-/** Add transfer batch to the list and queue.
- *
- * @param[in] instance List to use.
- * @param[in] batch Transfer batch to submit.
- *
- * The batch is added to the end of the list and queue.
- */
-void transfer_list_add_batch(
-    transfer_list_t *instance, usb_transfer_batch_t *batch)
-{
-	assert(instance);
-	assert(batch);
-	usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
-
-	fibril_mutex_lock(&instance->guard);
-
-	qh_t *last_qh = NULL;
-	/* Add to the hardware queue. */
-	if (list_empty(&instance->batch_list)) {
-		/* There is nothing scheduled */
-		last_qh = instance->queue_head;
-	} else {
-		/* There is something scheduled */
-		usb_transfer_batch_t *last =
-		    usb_transfer_batch_from_link(instance->batch_list.prev);
-		last_qh = batch_qh(last);
-	}
-	const uint32_t pa = addr_to_phys(batch_qh(batch));
-	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
-
-	/* Make sure all data in the batch are written */
-	write_barrier();
-
-	/* keep link */
-	batch_qh(batch)->next = last_qh->next;
-	qh_set_next_qh(last_qh, batch_qh(batch));
-
-	/* Make sure the pointer is updated */
-	write_barrier();
-
-	/* Add to the driver's list */
-	list_append(&batch->link, &instance->batch_list);
-
-	usb_transfer_batch_t *first = list_get_instance(
-	    instance->batch_list.next, usb_transfer_batch_t, link);
-	usb_log_debug("Batch(%p) added to queue %s, first is %p.\n",
-		batch, instance->name, first);
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Add completed bantches to the provided list.
- *
- * @param[in] instance List to use.
- * @param[in] done list to fill
- */
-void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)
-{
-	assert(instance);
-	assert(done);
-
-	fibril_mutex_lock(&instance->guard);
-	link_t *current = instance->batch_list.next;
-	while (current != &instance->batch_list) {
-		link_t * const next = current->next;
-		usb_transfer_batch_t *batch =
-		    usb_transfer_batch_from_link(current);
-
-		if (batch_is_complete(batch)) {
-			/* Save for processing */
-			transfer_list_remove_batch(instance, batch);
-			list_append(current, done);
-		}
-		current = next;
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Walk the list and finish all batches with EINTR.
- *
- * @param[in] instance List to use.
- */
-void transfer_list_abort_all(transfer_list_t *instance)
-{
-	fibril_mutex_lock(&instance->guard);
-	while (!list_empty(&instance->batch_list)) {
-		link_t * const current = instance->batch_list.next;
-		usb_transfer_batch_t *batch =
-		    usb_transfer_batch_from_link(current);
-		transfer_list_remove_batch(instance, batch);
-		usb_transfer_batch_finish_error(batch, EINTR);
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Remove a transfer batch from the list and queue.
- *
- * @param[in] instance List to use.
- * @param[in] batch Transfer batch to remove.
- *
- * Does not lock the transfer list, caller is responsible for that.
- */
-void transfer_list_remove_batch(
-    transfer_list_t *instance, usb_transfer_batch_t *batch)
-{
-	assert(instance);
-	assert(instance->queue_head);
-	assert(batch);
-	assert(batch_qh(batch));
-	assert(fibril_mutex_is_locked(&instance->guard));
-
-	usb_log_debug2(
-	    "Queue %s: removing batch(%p).\n", instance->name, batch);
-
-	const char *qpos = NULL;
-	qh_t *prev_qh = NULL;
-	/* Remove from the hardware queue */
-	if (instance->batch_list.next == &batch->link) {
-		/* I'm the first one here */
-		prev_qh = instance->queue_head;
-		qpos = "FIRST";
-	} else {
-		/* The thing before me is a batch too */
-		usb_transfer_batch_t *prev =
-		    usb_transfer_batch_from_link(batch->link.prev);
-		prev_qh = batch_qh(prev);
-		qpos = "NOT FIRST";
-	}
-	assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
-	    == addr_to_phys(batch_qh(batch)));
-	prev_qh->next = batch_qh(batch)->next;
-
-	/* Make sure the pointer is updated */
-	write_barrier();
-
-	/* Remove from the batch list */
-	list_remove(&batch->link);
-	usb_log_debug("Batch(%p) removed (%s) from %s, next: %x.\n",
-	    batch, qpos, instance->name, batch_qh(batch)->next);
-}
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci_hcd/transfer_list.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,66 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/** @addtogroup drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver transfer list structure
- */
-#ifndef DRV_UHCI_TRANSFER_LIST_H
-#define DRV_UHCI_TRANSFER_LIST_H
-
-#include <fibril_synch.h>
-#include <usb/host/batch.h>
-
-#include "hw_struct/queue_head.h"
-
-/** Structure maintaining both hw queue and software list
- * of currently executed transfers
- */
-typedef struct transfer_list {
-	/** Guard against multiple add/remove races */
-	fibril_mutex_t guard;
-	/** UHCI hw structure represeting this queue */
-	qh_t *queue_head;
-	/** Assigned name, for nicer debug output */
-	const char *name;
-	/** List of all batches in this list */
-	link_t batch_list;
-} transfer_list_t;
-
-void transfer_list_fini(transfer_list_t *instance);
-int transfer_list_init(transfer_list_t *instance, const char *name);
-void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
-void transfer_list_add_batch(
-    transfer_list_t *instance, usb_transfer_batch_t *batch);
-void transfer_list_remove_finished(transfer_list_t *instance, link_t *done);
-void transfer_list_abort_all(transfer_list_t *instance);
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/uhci.c
===================================================================
--- uspace/drv/uhci_hcd/uhci.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,286 +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 drvusbuhci
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/interrupt.h>
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
-#include <usb/debug.h>
-
-#include "uhci.h"
-#include "iface.h"
-#include "pci.h"
-
-#include "hc.h"
-#include "root_hub.h"
-
-/** Structure representing both functions of UHCI hc, USB host controller
- * and USB root hub */
-typedef struct uhci {
-	/** Pointer to DDF represenation of UHCI host controller */
-	ddf_fun_t *hc_fun;
-	/** Pointer to DDF represenation of UHCI root hub */
-	ddf_fun_t *rh_fun;
-
-	/** Internal driver's represenation of UHCI host controller */
-	hc_t hc;
-	/** Internal driver's represenation of UHCI root hub */
-	rh_t rh;
-} uhci_t;
-
-static inline uhci_t * dev_to_uhci(const ddf_dev_t *dev)
-{
-	assert(dev);
-	assert(dev->driver_data);
-	return dev->driver_data;
-}
-/*----------------------------------------------------------------------------*/
-/** IRQ handling callback, forward status from call to diver structure.
- *
- * @param[in] dev DDF instance of the device to use.
- * @param[in] iid (Unused).
- * @param[in] call Pointer to the call from kernel.
- */
-static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
-{
-	assert(dev);
-	uhci_t *uhci = dev_to_uhci(dev);
-	hc_t *hc = &uhci->hc;
-	const uint16_t status = IPC_GET_ARG1(*call);
-	assert(hc);
-	hc_interrupt(hc, status);
-}
-/*----------------------------------------------------------------------------*/
-/** Operations supported by the HC driver */
-static ddf_dev_ops_t hc_ops = {
-	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
-};
-/*----------------------------------------------------------------------------*/
-/** Get address of the device identified by handle.
- *
- * @param[in] fun DDF instance of the function to use.
- * @param[in] handle DDF handle of the driver seeking its USB address.
- * @param[out] address Found address.
- */
-static int usb_iface_get_address(
-    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
-{
-	assert(fun);
-	usb_device_keeper_t *manager = &dev_to_uhci(fun->dev)->hc.manager;
-	usb_address_t addr = usb_device_keeper_find(manager, handle);
-
-	if (addr < 0) {
-		return addr;
-	}
-
-	if (address != NULL) {
-		*address = addr;
-	}
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Gets handle of the respective hc.
- *
- * @param[in] fun DDF function of uhci device.
- * @param[out] handle Host cotnroller handle.
- * @return Error code.
- */
-static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
-{
-	assert(fun);
-	ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun;
-	assert(hc_fun);
-
-	if (handle != NULL)
-		*handle = hc_fun->handle;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** USB interface implementation used by RH */
-static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle,
-	.get_address = usb_iface_get_address
-};
-/*----------------------------------------------------------------------------*/
-/** Get root hub hw resources (I/O registers).
- *
- * @param[in] fun Root hub function.
- * @return Pointer to the resource list used by the root hub.
- */
-static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
-{
-	assert(fun);
-	rh_t *rh = fun->driver_data;
-	assert(rh);
-	return &rh->resource_list;
-}
-/*----------------------------------------------------------------------------*/
-/** Interface to provide the root hub driver with hw info */
-static hw_res_ops_t hw_res_iface = {
-	.get_resource_list = get_resource_list,
-	.enable_interrupt = NULL,
-};
-/*----------------------------------------------------------------------------*/
-/** RH function support for uhci_rhd */
-static ddf_dev_ops_t rh_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface,
-	.interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
-};
-/*----------------------------------------------------------------------------*/
-/** Initialize hc and rh DDF structures and their respective drivers.
- *
- * @param[in] device DDF instance of the device to use.
- *
- * This function does all the preparatory work for hc and rh drivers:
- *  - gets device's hw resources
- *  - disables UHCI legacy support (PCI config space)
- *  - attempts to enable interrupts
- *  - registers interrupt handler
- */
-int device_setup_uhci(ddf_dev_t *device)
-{
-	assert(device);
-	uhci_t *instance = malloc(sizeof(uhci_t));
-	if (instance == NULL) {
-		usb_log_error("Failed to allocate OHCI driver.\n");
-		return ENOMEM;
-	}
-
-#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
-if (ret != EOK) { \
-	if (instance->hc_fun) \
-		instance->hc_fun->ops = NULL; \
-		instance->hc_fun->driver_data = NULL; \
-		ddf_fun_destroy(instance->hc_fun); \
-	if (instance->rh_fun) {\
-		instance->rh_fun->ops = NULL; \
-		instance->rh_fun->driver_data = NULL; \
-		ddf_fun_destroy(instance->rh_fun); \
-	} \
-	free(instance); \
-	usb_log_error(message); \
-	return ret; \
-} else (void)0
-
-	instance->rh_fun = NULL;
-	instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc");
-	int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
-	instance->hc_fun->ops = &hc_ops;
-	instance->hc_fun->driver_data = &instance->hc;
-
-	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
-	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
-	instance->rh_fun->ops = &rh_ops;
-	instance->rh_fun->driver_data = &instance->rh;
-
-	uintptr_t reg_base = 0;
-	size_t reg_size = 0;
-	int irq = 0;
-
-	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed to get I/O addresses for %" PRIun ": %s.\n",
-	    device->handle, str_error(ret));
-	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
-	    (void *) reg_base, reg_size, irq);
-
-	ret = pci_disable_legacy(device);
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
-
-	bool interrupts = false;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, " \
-	    "falling back to polling.\n");
-#else
-	ret = pci_enable_interrupts(device);
-	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
-		    str_error(ret));
-		usb_log_info("HW interrupts not available, " \
-		    "falling back to polling.\n");
-	} else {
-		usb_log_debug("Hw interrupts enabled.\n");
-		interrupts = true;
-	}
-#endif
-
-
-	ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
-	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret));
-
-#define CHECK_RET_FINI_RETURN(ret, message...) \
-if (ret != EOK) { \
-	hc_fini(&instance->hc); \
-	CHECK_RET_DEST_FREE_RETURN(ret, message); \
-	return ret; \
-} else (void)0
-
-	/* It does no harm if we register this on polling */
-	ret = register_interrupt_handler(device, irq, irq_handler,
-	    &instance->hc.interrupt_code);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register interrupt handler: %s.\n",
-	    ret, str_error(ret));
-
-	ret = ddf_fun_bind(instance->hc_fun);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to bind UHCI device function: %s.\n",
-	    ret, str_error(ret));
-
-	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed to add UHCI to HC class: %s.\n", str_error(ret));
-
-	ret = rh_init(&instance->rh, instance->rh_fun,
-	    (uintptr_t)instance->hc.registers + 0x10, 4);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
-
-	ret = ddf_fun_bind(instance->rh_fun);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
-
-	device->driver_data = instance;
-	return EOK;
-#undef CHECK_RET_FINI_RETURN
-}
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/uhci.h
===================================================================
--- uspace/drv/uhci_hcd/uhci.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,43 +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 drvusbuhci
- * @{
- */
-/** @file
- * @brief UHCI driver main structure for both host controller and root-hub.
- */
-#ifndef DRV_UHCI_UHCI_H
-#define DRV_UHCI_UHCI_H
-#include <ddf/driver.h>
-
-int device_setup_uhci(ddf_dev_t *device);
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_hcd/uhci_hcd.ma
===================================================================
--- uspace/drv/uhci_hcd/uhci_hcd.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,29 +1,0 @@
-10 pci/ven=8086&dev=7020
-10 pci/ven=8086&dev=7112
-
-10 pci/ven=8086&dev=27c8
-10 pci/ven=8086&dev=27c9
-10 pci/ven=8086&dev=27ca
-10 pci/ven=8086&dev=27cb
-
-10 pci/ven=8086&dev=2830
-10 pci/ven=8086&dev=2831
-10 pci/ven=8086&dev=2832
-10 pci/ven=8086&dev=2834
-10 pci/ven=8086&dev=2835
-
-10 pci/ven=8086&dev=2934
-10 pci/ven=8086&dev=2935
-10 pci/ven=8086&dev=2936
-10 pci/ven=8086&dev=2937
-10 pci/ven=8086&dev=2938
-10 pci/ven=8086&dev=2939
-
-10 pci/ven=8086&dev=24c2
-10 pci/ven=8086&dev=24c4
-10 pci/ven=8086&dev=24c7
-
-10 pci/ven=8086&dev=2688
-10 pci/ven=8086&dev=2689
-10 pci/ven=8086&dev=268a
-10 pci/ven=8086&dev=268b
Index: pace/drv/uhci_hcd/utils/malloc32.h
===================================================================
--- uspace/drv/uhci_hcd/utils/malloc32.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,114 +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 drvusbuhci
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_UTILS_MALLOC32_H
-#define DRV_UHCI_UTILS_MALLOC32_H
-
-#include <assert.h>
-#include <errno.h>
-#include <malloc.h>
-#include <mem.h>
-#include <as.h>
-
-#define UHCI_STRCUTURES_ALIGNMENT 16
-#define UHCI_REQUIRED_PAGE_SIZE 4096
-
-
-/** Get physical address translation
- *
- * @param[in] addr Virtual address to translate
- * @return Physical address if exists, NULL otherwise.
- */
-static inline uintptr_t addr_to_phys(void *addr)
-{
-	if (addr == NULL)
-		return 0;
-
-	uintptr_t result;
-	const int ret = as_get_physical_mapping(addr, &result);
-	if (ret != EOK)
-		return 0;
-	return (result | ((uintptr_t)addr & 0xfff));
-}
-/*----------------------------------------------------------------------------*/
-/** Physical mallocator simulator
- *
- * @param[in] size Size of the required memory space
- * @return Address of the alligned and big enough memory place, NULL on failure.
- */
-static inline void * malloc32(size_t size) {
-	/* This works only when the host has less than 4GB of memory as
-	 * physical address needs to fit into 32 bits */
-
-	/* If we need more than one page there is no guarantee that the
-	 * memory will be continuous */
-	if (size > PAGE_SIZE)
-		return NULL;
-	/* Calculate alignment to make sure the block won't cross page
-	 * boundary */
-	size_t alignment = UHCI_STRCUTURES_ALIGNMENT;
-	while (alignment < size)
-		alignment *= 2;
-	return memalign(alignment, size);
-}
-/*----------------------------------------------------------------------------*/
-/** Physical mallocator simulator
- *
- * @param[in] addr Address of the place allocated by malloc32
- */
-static inline void free32(void *addr) {
-	if (!addr)
-		return;
-	free(addr);
-}
-/*----------------------------------------------------------------------------*/
-/** Create 4KB page mapping
- *
- * @return Address of the mapped page, NULL on failure.
- */
-static inline void * get_page(void)
-{
-	void *free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
-	if (free_address == 0)
-		return NULL;
-	void *ret = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
-		  AS_AREA_READ | AS_AREA_WRITE);
-	if (ret != free_address)
-		return NULL;
-	return ret;
-}
-
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_rhd/Makefile
===================================================================
--- uspace/drv/uhci_rhd/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,47 +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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = uhci_rhd
-
-SOURCES = \
-	main.c \
-	port.c \
-	root_hub.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/uhci_rhd/main.c
===================================================================
--- uspace/drv/uhci_rhd/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,182 +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 drvusbuhcirh
- * @{
- */
-/** @file
- * @brief UHCI root hub initialization routines
- */
-
-#include <ddf/driver.h>
-#include <devman.h>
-#include <device/hw_res.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
-#include <usb/debug.h>
-
-#include "root_hub.h"
-
-#define NAME "uhci_rhd"
-
-static int hc_get_my_registers(const ddf_dev_t *dev,
-    uintptr_t *io_reg_address, size_t *io_reg_size);
-
-static int uhci_rh_add_device(ddf_dev_t *device);
-
-static driver_ops_t uhci_rh_driver_ops = {
-	.add_device = uhci_rh_add_device,
-};
-
-static driver_t uhci_rh_driver = {
-	.name = NAME,
-	.driver_ops = &uhci_rh_driver_ops
-};
-
-/** Initialize global driver structures (NONE).
- *
- * @param[in] argc Nmber of arguments in argv vector (ignored).
- * @param[in] argv Cmdline argument vector (ignored).
- * @return Error code.
- *
- * Driver debug level is set here.
- */
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS UHCI root hub driver.\n");
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-	return ddf_driver_main(&uhci_rh_driver);
-}
-
-/** Initialize a new ddf driver instance of UHCI root hub.
- *
- * @param[in] device DDF instance of the device to initialize.
- * @return Error code.
- */
-static int uhci_rh_add_device(ddf_dev_t *device)
-{
-	if (!device)
-		return EINVAL;
-
-	usb_log_debug2("uhci_rh_add_device(handle=%" PRIun ")\n",
-	    device->handle);
-
-	uintptr_t io_regs = 0;
-	size_t io_size = 0;
-	uhci_root_hub_t *rh = NULL;
-	int ret = EOK;
-
-#define CHECK_RET_FREE_RH_RETURN(ret, message...) \
-if (ret != EOK) { \
-	usb_log_error(message); \
-	if (rh) \
-		free(rh); \
-	return ret; \
-} else (void)0
-
-	ret = hc_get_my_registers(device, &io_regs, &io_size);
-	CHECK_RET_FREE_RH_RETURN(ret,
-	    "Failed to get registers from HC: %s.\n", str_error(ret));
-	usb_log_debug("I/O regs at %p (size %zuB).\n",
-	    (void *) io_regs, io_size);
-
-	rh = malloc(sizeof(uhci_root_hub_t));
-	ret = (rh == NULL) ? ENOMEM : EOK;
-	CHECK_RET_FREE_RH_RETURN(ret,
-	    "Failed to allocate rh driver instance.\n");
-
-	ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
-	CHECK_RET_FREE_RH_RETURN(ret,
-	    "Failed(%d) to initialize rh driver instance: %s.\n",
-	    ret, str_error(ret));
-
-	device->driver_data = rh;
-	usb_log_info("Controlling root hub '%s' (%" PRIun ").\n",
-	    device->name, device->handle);
-	return EOK;
-}
-
-/** Get address of I/O registers.
- *
- * @param[in] dev Device asking for the addresses.
- * @param[out] io_reg_address Base address of the memory range.
- * @param[out] io_reg_size Size of the memory range.
- * @return Error code.
- */
-int hc_get_my_registers(
-    const ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
-{
-	assert(dev);
-	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	hw_resource_list_t hw_resources;
-	const int ret = hw_res_get_resource_list(parent_sess, &hw_resources);
-	if (ret != EOK) {
-		async_hangup(parent_sess);
-		return ret;
-	}
-	
-	uintptr_t io_address = 0;
-	size_t io_size = 0;
-	bool io_found = false;
-	
-	size_t i = 0;
-	for (; i < hw_resources.count; i++) {
-		hw_resource_t *res = &hw_resources.resources[i];
-		if (res->type == IO_RANGE) {
-			io_address = res->res.io_range.address;
-			io_size = res->res.io_range.size;
-			io_found = true;
-		}
-	
-	}
-	async_hangup(parent_sess);
-	
-	if (!io_found)
-		return ENOENT;
-	
-	if (io_reg_address != NULL)
-		*io_reg_address = io_address;
-	
-	if (io_reg_size != NULL)
-		*io_reg_size = io_size;
-	
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/drv/uhci_rhd/port.c
===================================================================
--- uspace/drv/uhci_rhd/port.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,355 +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 drvusbuhcirh
- * @{
- */
-/** @file
- * @brief UHCI root hub port routines
- */
-#include <libarch/ddi.h>  /* pio_read and pio_write */
-#include <fibril_synch.h> /* async_usleep */
-#include <errno.h>
-#include <str_error.h>
-#include <async.h>
-
-#include <usb/usb.h>    /* usb_address_t */
-#include <usb/dev/hub.h>    /* usb_hc_new_device_wrapper */
-#include <usb/debug.h>
-
-#include "port.h"
-
-static int uhci_port_check(void *port);
-static int uhci_port_reset_enable(int portno, void *arg);
-static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
-static int uhci_port_remove_device(uhci_port_t *port);
-static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
-static void uhci_port_print_status(
-    uhci_port_t *port, const port_status_t value);
-
-/** Register reading helper function.
- *
- * @param[in] port Structure to use.
- * @return Error code. (Always EOK)
- */
-static inline port_status_t uhci_port_read_status(uhci_port_t *port)
-{
-	assert(port);
-	return pio_read_16(port->address);
-}
-/*----------------------------------------------------------------------------*/
-/** Register writing helper function.
- *
- * @param[in] port Structure to use.
- * @param[in] val New register value.
- * @return Error code. (Always EOK)
- */
-static inline void uhci_port_write_status(uhci_port_t *port, port_status_t val)
-{
-	assert(port);
-	pio_write_16(port->address, val);
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize UHCI root hub port instance.
- *
- * @param[in] port Memory structure to use.
- * @param[in] address Address of I/O register.
- * @param[in] number Port number.
- * @param[in] usec Polling interval.
- * @param[in] rh Pointer to ddf instance of the root hub driver.
- * @return Error code.
- *
- * Creates and starts the polling fibril.
- */
-int uhci_port_init(uhci_port_t *port,
-    port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh)
-{
-	assert(port);
-	char *id_string;
-	asprintf(&id_string, "Port (%p - %u)", port, number);
-	if (id_string == NULL) {
-		return ENOMEM;
-	}
-
-	port->id_string = id_string;
-	port->address = address;
-	port->number = number;
-	port->wait_period_usec = usec;
-	port->attached_device = 0;
-	port->rh = rh;
-
-	int ret =
-	    usb_hc_connection_initialize_from_device(&port->hc_connection, rh);
-	if (ret != EOK) {
-		usb_log_error("%s: failed to initialize connection to HC.",
-		    port->id_string);
-		free(id_string);
-		return ret;
-	}
-
-	port->checker = fibril_create(uhci_port_check, port);
-	if (port->checker == 0) {
-		usb_log_error("%s: failed to create polling fibril.",
-		    port->id_string);
-		free(id_string);
-		return ENOMEM;
-	}
-
-	fibril_add_ready(port->checker);
-	usb_log_debug("%s: Started polling fibril (%" PRIun ").\n",
-	    port->id_string, port->checker);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Cleanup UHCI root hub port instance.
- *
- * @param[in] port Memory structure to use.
- *
- * Stops the polling fibril.
- */
-void uhci_port_fini(uhci_port_t *port)
-{
-	assert(port);
-	free(port->id_string);
-	// TODO: Kill fibril here
-	return;
-}
-/*----------------------------------------------------------------------------*/
-/** Periodically checks port status and reports new devices.
- *
- * @param[in] port Port structure to use.
- * @return Error code.
- */
-int uhci_port_check(void *port)
-{
-	uhci_port_t *instance = port;
-	assert(instance);
-
-	while (1) {
-		async_usleep(instance->wait_period_usec);
-
-		/* Read register value */
-		const port_status_t port_status =
-		    uhci_port_read_status(instance);
-
-		/* Print the value if it's interesting */
-		if (port_status & ~STATUS_ALWAYS_ONE)
-			uhci_port_print_status(instance, port_status);
-
-		if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
-			continue;
-
-		usb_log_debug("%s: Connected change detected: %x.\n",
-		    instance->id_string, port_status);
-
-		/* Remove any old device */
-		if (instance->attached_device) {
-			usb_log_debug2("%s: Removing device.\n",
-			    instance->id_string);
-			uhci_port_remove_device(instance);
-		}
-
-		int ret =
-		    usb_hc_connection_open(&instance->hc_connection);
-		if (ret != EOK) {
-			usb_log_error("%s: Failed to connect to HC.",
-			    instance->id_string);
-			continue;
-		}
-
-		if ((port_status & STATUS_CONNECTED) != 0) {
-			/* New device */
-			const usb_speed_t speed =
-			    ((port_status & STATUS_LOW_SPEED) != 0) ?
-			    USB_SPEED_LOW : USB_SPEED_FULL;
-			uhci_port_new_device(instance, speed);
-		} else {
-			/* Write one to WC bits, to ack changes */
-			uhci_port_write_status(instance, port_status);
-			usb_log_debug("%s: status change ACK.\n",
-			    instance->id_string);
-		}
-
-		ret = usb_hc_connection_close(&instance->hc_connection);
-		if (ret != EOK) {
-			usb_log_error("%s: Failed to disconnect.",
-			    instance->id_string);
-		}
-	}
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Callback for enabling port during adding a new device.
- *
- * @param portno Port number (unused).
- * @param arg Pointer to uhci_port_t of port with the new device.
- * @return Error code.
- *
- * Resets and enables the ub port.
- */
-int uhci_port_reset_enable(int portno, void *arg)
-{
-	uhci_port_t *port = arg;
-	assert(port);
-
-	usb_log_debug2("%s: new_device_enable_port.\n", port->id_string);
-
-	/*
-	 * Resets from root ports should be nominally 50ms (USB spec 7.1.7.3)
-	 */
-	{
-		usb_log_debug("%s: Reset Signal start.\n", port->id_string);
-		port_status_t port_status = uhci_port_read_status(port);
-		port_status |= STATUS_IN_RESET;
-		uhci_port_write_status(port, port_status);
-		async_usleep(50000);
-		port_status = uhci_port_read_status(port);
-		port_status &= ~STATUS_IN_RESET;
-		uhci_port_write_status(port, port_status);
-		while (uhci_port_read_status(port) & STATUS_IN_RESET);
-	}
-	/* PIO delay, should not be longer than 3ms as the device might
-	 * enter suspend state. */
-	udelay(10);
-	/* Enable the port. */
-	uhci_port_set_enabled(port, true);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Initialize and report connected device.
- *
- * @param[in] port Port structure to use.
- * @param[in] speed Detected speed.
- * @return Error code.
- *
- * Uses libUSB function to do the actual work.
- */
-int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed)
-{
-	assert(port);
-	assert(usb_hc_connection_is_opened(&port->hc_connection));
-
-	usb_log_debug("%s: Detected new device.\n", port->id_string);
-
-	int ret, count = 0;
-	usb_address_t dev_addr;
-	do {
-		ret = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
-		    speed, uhci_port_reset_enable, port->number, port,
-		    &dev_addr, &port->attached_device, NULL, NULL, NULL);
-	} while (ret != EOK && ++count < 4);
-
-	if (ret != EOK) {
-		usb_log_error("%s: Failed(%d) to add device: %s.\n",
-		    port->id_string, ret, str_error(ret));
-		uhci_port_set_enabled(port, false);
-		return ret;
-	}
-
-	usb_log_info("New device at port %u, address %d (handle %" PRIun ").\n",
-	    port->number, dev_addr, port->attached_device);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Remove device.
- *
- * @param[in] port Memory structure to use.
- * @return Error code.
- *
- * Does not work, DDF does not support device removal.
- * Does not even free used USB address (it would be dangerous if tis driver
- * is still running).
- */
-int uhci_port_remove_device(uhci_port_t *port)
-{
-	usb_log_error("%s: Don't know how to remove device %" PRIun ".\n",
-	    port->id_string, port->attached_device);
-	port->attached_device = 0;
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-/** Enable or disable root hub port.
- *
- * @param[in] port Port structure to use.
- * @param[in] enabled Port status to set.
- * @return Error code. (Always EOK)
- */
-int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
-{
-	assert(port);
-
-	/* Read register value */
-	port_status_t port_status = uhci_port_read_status(port);
-
-	/* Set enabled bit */
-	if (enabled) {
-		port_status |= STATUS_ENABLED;
-	} else {
-		port_status &= ~STATUS_ENABLED;
-	}
-
-	/* Write new value. */
-	uhci_port_write_status(port, port_status);
-
-	/* Wait for port to become enabled */
-	do {
-		port_status = uhci_port_read_status(port);
-	} while ((port_status & STATUS_CONNECTED) &&
-	    !(port_status & STATUS_ENABLED));
-
-	usb_log_debug("%s: %sabled port.\n",
-		port->id_string, enabled ? "En" : "Dis");
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Print the port status value in a human friendly way
- *
- * @param[in] port Port structure to use.
- * @param[in] value Port register value to print.
- * @return Error code. (Always EOK)
- */
-void uhci_port_print_status(uhci_port_t *port, const port_status_t value)
-{
-	assert(port);
-	usb_log_debug2("%s Port status(%#x):%s%s%s%s%s%s%s%s%s%s%s.\n",
-	    port->id_string, value,
-	    (value & STATUS_SUSPEND) ? " SUSPENDED," : "",
-	    (value & STATUS_RESUME) ? " IN RESUME," : "",
-	    (value & STATUS_IN_RESET) ? " IN RESET," : "",
-	    (value & STATUS_LINE_D_MINUS) ? " VD-," : "",
-	    (value & STATUS_LINE_D_PLUS) ? " VD+," : "",
-	    (value & STATUS_LOW_SPEED) ? " LOWSPEED," : "",
-	    (value & STATUS_ENABLED_CHANGED) ? " ENABLED-CHANGE," : "",
-	    (value & STATUS_ENABLED) ? " ENABLED," : "",
-	    (value & STATUS_CONNECTED_CHANGED) ? " CONNECTED-CHANGE," : "",
-	    (value & STATUS_CONNECTED) ? " CONNECTED," : "",
-	    (value & STATUS_ALWAYS_ONE) ? " ALWAYS ONE" : " ERR: NO ALWAYS ONE"
-	);
-}
-/**
- * @}
- */
Index: pace/drv/uhci_rhd/port.h
===================================================================
--- uspace/drv/uhci_rhd/port.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,77 +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 drvusbuhcirh
- * @{
- */
-/** @file
- * @brief UHCI root hub port routines
- */
-#ifndef DRV_UHCI_PORT_H
-#define DRV_UHCI_PORT_H
-
-#include <stdint.h>
-#include <fibril.h>
-#include <ddf/driver.h>
-#include <usb/hc.h> /* usb_hc_connection_t */
-
-typedef uint16_t port_status_t;
-#define STATUS_CONNECTED         (1 << 0)
-#define STATUS_CONNECTED_CHANGED (1 << 1)
-#define STATUS_ENABLED           (1 << 2)
-#define STATUS_ENABLED_CHANGED   (1 << 3)
-#define STATUS_LINE_D_PLUS       (1 << 4)
-#define STATUS_LINE_D_MINUS      (1 << 5)
-#define STATUS_RESUME            (1 << 6)
-#define STATUS_ALWAYS_ONE        (1 << 7)
-
-#define STATUS_LOW_SPEED (1 <<  8)
-#define STATUS_IN_RESET  (1 <<  9)
-#define STATUS_SUSPEND   (1 << 12)
-
-/** UHCI port structure */
-typedef struct uhci_port {
-	const char *id_string;
-	port_status_t *address;
-	unsigned number;
-	unsigned wait_period_usec;
-	usb_hc_connection_t hc_connection;
-	ddf_dev_t *rh;
-	devman_handle_t attached_device;
-	fid_t checker;
-} uhci_port_t;
-
-int uhci_port_init(
-    uhci_port_t *port, port_status_t *address, unsigned number,
-    unsigned usec, ddf_dev_t *rh);
-
-void uhci_port_fini(uhci_port_t *port);
-
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_rhd/root_hub.c
===================================================================
--- uspace/drv/uhci_rhd/root_hub.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,97 +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 drvusbuhcirh
- * @{
- */
-/** @file
- * @brief UHCI root hub driver
- */
-#include <errno.h>
-#include <str_error.h>
-#include <ddi.h>
-#include <usb/debug.h>
-
-#include "root_hub.h"
-
-/** Initialize UHCI root hub instance.
- *
- * @param[in] instance Driver memory structure to use.
- * @param[in] addr Address of I/O registers.
- * @param[in] size Size of available I/O space.
- * @param[in] rh Pointer to DDF instance of the root hub driver.
- * @return Error code.
- */
-int uhci_root_hub_init(
-  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
-{
-	assert(instance);
-	assert(rh);
-
-	/* Allow access to root hub port registers */
-	assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);
-	port_status_t *regs;
-	int ret = pio_enable(addr, size, (void**)&regs);
-	if (ret < 0) {
-		usb_log_error(
-		    "Failed(%d) to gain access to port registers at %p: %s.\n",
-		    ret, regs, str_error(ret));
-		return ret;
-	}
-
-	/* Initialize root hub ports */
-	unsigned i = 0;
-	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
-		ret = uhci_port_init(
-		    &instance->ports[i], &regs[i], i, ROOT_HUB_WAIT_USEC, rh);
-		if (ret != EOK) {
-			unsigned j = 0;
-			for (;j < i; ++j)
-				uhci_port_fini(&instance->ports[j]);
-			return ret;
-		}
-	}
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Cleanup UHCI root hub instance.
- *
- * @param[in] instance Root hub structure to use.
- */
-void uhci_root_hub_fini(uhci_root_hub_t* instance)
-{
-	assert(instance);
-	unsigned i = 0;
-	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
-		uhci_port_fini(&instance->ports[i]);
-	}
-}
-/*----------------------------------------------------------------------------*/
-/**
- * @}
- */
Index: pace/drv/uhci_rhd/root_hub.h
===================================================================
--- uspace/drv/uhci_rhd/root_hub.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,57 +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 drvusbuhcirh
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef DRV_UHCI_ROOT_HUB_H
-#define DRV_UHCI_ROOT_HUB_H
-
-#include <ddf/driver.h>
-
-#include "port.h"
-
-#define UHCI_ROOT_HUB_PORT_COUNT 2
-#define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */
-
-/** UHCI root hub drvier structure */
-typedef struct root_hub {
-	/** Ports provided by the hub */
-	uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
-} uhci_root_hub_t;
-
-int uhci_root_hub_init(
-    uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
-
-void uhci_root_hub_fini(uhci_root_hub_t *instance);
-#endif
-/**
- * @}
- */
Index: pace/drv/uhci_rhd/uhci_rhd.ma
===================================================================
--- uspace/drv/uhci_rhd/uhci_rhd.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 usb&uhci&root-hub
Index: pace/drv/usbflbk/Makefile
===================================================================
--- uspace/drv/usbflbk/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,45 +1,0 @@
-#
-# 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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = usbflbk
-
-SOURCES = \
-	main.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/usbflbk/main.c
===================================================================
--- uspace/drv/usbflbk/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,95 +1,0 @@
-/*
- * 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 drvusbfallback
- * @{
- */
-/**
- * @file
- * Main routines of USB fallback driver.
- */
-#include <usb/dev/driver.h>
-#include <usb/debug.h>
-#include <errno.h>
-#include <str_error.h>
-
-#define NAME "usbflbk"
-
-/** Callback when new device is attached and recognized by DDF.
- *
- * @param dev Representation of a generic DDF device.
- * @return Error code.
- */
-static int usbfallback_add_device(usb_device_t *dev)
-{
-	int rc;
-	const char *fun_name = "ctl";
-
-	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
-	    fun_name);
-	if (ctl_fun == NULL) {
-		usb_log_error("Failed to create control function.\n");
-		return ENOMEM;
-	}
-	rc = ddf_fun_bind(ctl_fun);
-	if (rc != EOK) {
-		usb_log_error("Failed to bind control function: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	usb_log_info("Pretending to control %s `%s'" \
-	    " (node `%s', handle %" PRIun ").\n",
-	    dev->interface_no < 0 ? "device" : "interface",
-	    dev->ddf_dev->name, fun_name, dev->ddf_dev->handle);
-
-	return EOK;
-}
-
-/** USB fallback driver ops. */
-static usb_driver_ops_t usbfallback_driver_ops = {
-	.add_device = usbfallback_add_device,
-};
-
-/** USB fallback driver. */
-static usb_driver_t usbfallback_driver = {
-	.name = NAME,
-	.ops = &usbfallback_driver_ops,
-	.endpoints = NULL
-};
-
-int main(int argc, char *argv[])
-{
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-
-	return usb_driver_main(&usbfallback_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbflbk/usbflbk.ma
===================================================================
--- uspace/drv/usbflbk/usbflbk.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,2 +1,0 @@
-10 usb&fallback
-10 usb&interface&fallback
Index: pace/drv/usbhid/Makefile
===================================================================
--- uspace/drv/usbhid/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,58 +1,0 @@
-#
-# Copyright (c) 2010-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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBHID_PREFIX)/libusbhid.a \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I. \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBUSBHID_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = usbhid
-
-SOURCES = \
-	main.c \
-	usbhid.c \
-	subdrivers.c \
-	kbd/conv.c \
-	kbd/kbddev.c \
-	kbd/kbdrepeat.c \
-	generic/hiddev.c \
-	mouse/mousedev.c \
-	multimedia/multimedia.c \
-	multimedia/keymap.c \
-	$(STOLEN_LAYOUT_SOURCES)
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/usbhid/generic/hiddev.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,244 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/**
- * @file
- * USB HID driver API.
- */
-
-#include <usb/debug.h>
-#include <usb/classes/classes.h>
-#include <errno.h>
-#include <str_error.h>
-#include <bool.h>
-
-#include <usbhid_iface.h>
-
-#include "hiddev.h"
-#include "usbhid.h"
-
-/*----------------------------------------------------------------------------*/
-
-usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
-	.transfer_type = USB_TRANSFER_INTERRUPT,
-	.direction = USB_DIRECTION_IN,
-	.interface_class = USB_CLASS_HID,
-	.flags = 0
-};
-
-const char *HID_GENERIC_FUN_NAME = "hid";
-const char *HID_GENERIC_CLASS_NAME = "hid";
-
-/*----------------------------------------------------------------------------*/
-
-static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
-
-static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
-    size_t size, size_t *act_size, int *event_nr, unsigned int flags);
-
-static int usb_generic_hid_client_connected(ddf_fun_t *fun);
-
-static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun);
-
-static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
-    size_t size, size_t *actual_size);
-
-/*----------------------------------------------------------------------------*/
-
-static usbhid_iface_t usb_generic_iface = {
-	.get_event = usb_generic_hid_get_event,
-	.get_event_length = usb_generic_hid_get_event_length,
-	.get_report_descriptor_length = usb_generic_get_report_descriptor_length,
-	.get_report_descriptor = usb_generic_get_report_descriptor
-};
-
-static ddf_dev_ops_t usb_generic_hid_ops = {
-	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
-	.open = usb_generic_hid_client_connected
-};
-
-/*----------------------------------------------------------------------------*/
-
-static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
-{
-	usb_log_debug2("Generic HID: Get event length (fun: %p, "
-	    "fun->driver_data: %p.\n", fun, fun->driver_data);
-	
-	if (fun == NULL || fun->driver_data == NULL) {
-		return 0;
-	}
-
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
-	
-	usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
-	    hid_dev, hid_dev->max_input_report_size);
-	
-	return hid_dev->max_input_report_size;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
-    size_t size, size_t *act_size, int *event_nr, unsigned int flags)
-{
-	usb_log_debug2("Generic HID: Get event.\n");
-	
-	if (fun == NULL || fun->driver_data == NULL || buffer == NULL
-	    || act_size == NULL || event_nr == NULL) {
-		usb_log_debug("No function");
-		return EINVAL;
-	}
-
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
-	
-	if (hid_dev->input_report_size > size) {
-		usb_log_debug("input_report_size > size (%zu, %zu)\n", 
-		    hid_dev->input_report_size, size);
-		return EINVAL;	// TODO: other error code
-	}
-	
-	/*! @todo This should probably be somehow atomic. */
-	memcpy(buffer, hid_dev->input_report, 
-	    hid_dev->input_report_size);
-	*act_size = hid_dev->input_report_size;
-	*event_nr = usb_hid_report_number(hid_dev);
-	
-	usb_log_debug2("OK\n");
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
-{
-	usb_log_debug("Generic HID: Get report descriptor length.\n");
-	
-	if (fun == NULL || fun->driver_data == NULL) {
-		usb_log_debug("No function");
-		return EINVAL;
-	}
-	
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
-	
-	usb_log_debug2("hid_dev->report_desc_size = %zu\n", 
-	    hid_dev->report_desc_size);
-	
-	return hid_dev->report_desc_size;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
-    size_t size, size_t *actual_size)
-{
-	usb_log_debug2("Generic HID: Get report descriptor.\n");
-	
-	if (fun == NULL || fun->driver_data == NULL) {
-		usb_log_debug("No function");
-		return EINVAL;
-	}
-	
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
-	
-	if (hid_dev->report_desc_size > size) {
-		return EINVAL;
-	}
-	
-	memcpy(desc, hid_dev->report_desc, hid_dev->report_desc_size);
-	*actual_size = hid_dev->report_desc_size;
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_generic_hid_client_connected(ddf_fun_t *fun)
-{
-	usb_log_debug("Generic HID: Client connected.\n");
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)
-{	
-	/* Create the function exposed under /dev/devices. */
-	/** @todo Generate numbers for the devices? */
-	usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
-	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
-	    HID_GENERIC_FUN_NAME);
-	if (fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	fun->ops = &usb_generic_hid_ops;
-	fun->driver_data = hid_dev;
-
-	int rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
-{
-	if (hid_dev == NULL) {
-		return EINVAL;
-	}
-	
-	return usb_generic_hid_create_function(hid_dev);
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data, 
-    uint8_t *buffer, size_t buffer_size)
-{
-	usb_log_debug2("usb_hid_polling_callback(%p, %p, %zu)\n",
-	    hid_dev, buffer, buffer_size);
-	usb_debug_str_buffer(buffer, buffer_size, 0);
-	return true;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/generic/hiddev.h
===================================================================
--- uspace/drv/usbhid/generic/hiddev.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB HID driver API.
- */
-
-#ifndef USB_HID_HIDDDEV_H_
-#define USB_HID_HIDDDEV_H_
-
-#include <usb/dev/driver.h>
-
-struct usb_hid_dev;
-
-usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
-
-const char *HID_GENERIC_FUN_NAME;
-const char *HID_GENERIC_CLASS_NAME;
-
-/*----------------------------------------------------------------------------*/
-
-int usb_generic_hid_init(struct usb_hid_dev *hid_dev, void **data);
-
-bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev, void *data,
-    uint8_t *buffer, size_t buffer_size);
-
-#endif // USB_HID_HIDDDEV_H_
-
-/**
- * @}
- */
Index: pace/drv/usbhid/kbd/conv.c
===================================================================
--- uspace/drv/usbhid/kbd/conv.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,194 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB scancode parser.
- */
-
-#include <io/keycode.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <usb/debug.h>
-#include "conv.h"
-
-/**
- * Mapping between USB HID key codes (from HID Usage Tables) and corresponding
- * HelenOS key codes.
- */
-static int scanmap_simple[255] = {
-
-//	[0x29] = KC_BACKTICK,
-
-//	[0x02] = KC_1,
-//	[0x03] = KC_2,
-	[0x04] = KC_A,
-	[0x05] = KC_B,
-	[0x06] = KC_C,
-	[0x07] = KC_D,
-	[0x08] = KC_E,
-	[0x09] = KC_F,
-	[0x0a] = KC_G,
-	[0x0b] = KC_H,
-	[0x0c] = KC_I,
-	[0x0d] = KC_J,
-	[0x0e] = KC_K,
-	[0x0f] = KC_L,
-	[0x10] = KC_M,
-	[0x11] = KC_N,
-	[0x12] = KC_O,
-	[0x13] = KC_P,
-	[0x14] = KC_Q,
-	[0x15] = KC_R,
-	[0x16] = KC_S,
-	[0x17] = KC_T,
-	[0x18] = KC_U,
-	[0x19] = KC_V,
-	[0x1a] = KC_W,
-	[0x1b] = KC_X,
-	[0x1c] = KC_Y,
-	[0x1d] = KC_Z,
-
-	[0x1e] = KC_1,
-	[0x1f] = KC_2,
-	[0x20] = KC_3,
-	[0x21] = KC_4,
-	[0x22] = KC_5,
-	[0x23] = KC_6,
-	[0x24] = KC_7,
-	[0x25] = KC_8,
-	[0x26] = KC_9,
-	[0x27] = KC_0,
-	
-	[0x28] = KC_ENTER,
-	[0x29] = KC_ESCAPE,
-	[0x2a] = KC_BACKSPACE,
-	[0x2b] = KC_TAB,
-	[0x2c] = KC_SPACE,
-
-	[0x2d] = KC_MINUS,  // same as DASH? (- or _)
-	[0x2e] = KC_EQUALS,
-	[0x2f] = KC_LBRACKET,
-	[0x30] = KC_RBRACKET,
-	[0x31] = KC_BACKSLASH,
-	//[0x32] = KC_,	// TODO: HASH??? maybe same as 0x31 - backslash
-	[0x32] = KC_BACKSLASH,
-	[0x33] = KC_SEMICOLON,
-	[0x34] = KC_QUOTE,  // same as APOSTROPHE? (')
-	[0x35] = KC_BACKTICK,  // same as GRAVE ACCENT?? (`)
-	[0x36] = KC_COMMA,
-	[0x37] = KC_PERIOD,
-	[0x38] = KC_SLASH,
-
-	[0x39] = KC_CAPS_LOCK,
-	
-	[0x3a] = KC_F1,
-	[0x3b] = KC_F2,
-	[0x3c] = KC_F3,
-	[0x3d] = KC_F4,
-	[0x3e] = KC_F5,
-	[0x3f] = KC_F6,
-	[0x40] = KC_F7,
-	[0x41] = KC_F8,
-	[0x42] = KC_F9,
-	[0x43] = KC_F10,
-	[0x44] = KC_F11,
-	[0x45] = KC_F12,
-	
-	[0x46] = KC_PRTSCR,
-	[0x47] = KC_SCROLL_LOCK,
-	[0x48] = KC_PAUSE,
-	[0x49] = KC_INSERT,
-	[0x4a] = KC_HOME,
-	[0x4b] = KC_PAGE_UP,
-	[0x4c] = KC_DELETE,
-	[0x4d] = KC_END,
-	[0x4e] = KC_PAGE_DOWN,
-	[0x4f] = KC_RIGHT,
-	[0x50] = KC_LEFT,
-	[0x51] = KC_DOWN,
-	[0x52] = KC_UP,
-	
-	//[0x64] = // some funny key
-	
-	[0xe0] = KC_LCTRL,
-	[0xe1] = KC_LSHIFT,
-	[0xe2] = KC_LALT,
-	//[0xe3] = KC_L	// TODO: left GUI
-	[0xe4] = KC_RCTRL,
-	[0xe5] = KC_RSHIFT,
-	[0xe6] = KC_RALT,
-	//[0xe7] = KC_R	// TODO: right GUI
-	
-	[0x53] = KC_NUM_LOCK,
-	[0x54] = KC_NSLASH,
-	[0x55] = KC_NTIMES,
-	[0x56] = KC_NMINUS,
-	[0x57] = KC_NPLUS,
-	[0x58] = KC_NENTER,
-	[0x59] = KC_N1,
-	[0x5a] = KC_N2,
-	[0x5b] = KC_N3,
-	[0x5c] = KC_N4,
-	[0x5d] = KC_N5,
-	[0x5e] = KC_N6,
-	[0x5f] = KC_N7,
-	[0x60] = KC_N8,
-	[0x61] = KC_N9,
-	[0x62] = KC_N0,
-	[0x63] = KC_NPERIOD
-	
-};
-
-/**
- * Translate USB HID key codes (from HID Usage Tables) to generic key codes
- * recognized by HelenOS.
- *
- * @param scancode USB HID key code (from HID Usage Tables).
- * 
- * @retval HelenOS key code corresponding to the given USB HID key code.
- */
-unsigned int usbhid_parse_scancode(int scancode)
-{
-	unsigned int key;
-	int *map = scanmap_simple;
-	size_t map_length = sizeof(scanmap_simple) / sizeof(int);
-
-	if ((scancode < 0) || ((size_t) scancode >= map_length))
-		return -1;
-
-	key = map[scancode];
-	
-	return key;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/kbd/conv.h
===================================================================
--- uspace/drv/usbhid/kbd/conv.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB scancode parser.
- */
-
-#ifndef USB_HID_CONV_H_
-#define USB_HID_CONV_H_
-
-unsigned int usbhid_parse_scancode(int scancode);
-
-#endif /* USB_HID_CONV_H_ */
-
-/**
- * @}
- */
Index: pace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,877 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/**
- * @file
- * USB HID keyboard device structure and API.
- */
-
-#include <errno.h>
-#include <str_error.h>
-#include <stdio.h>
-
-#include <io/keycode.h>
-#include <io/console.h>
-#include <ipc/kbdev.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <fibril.h>
-#include <fibril_synch.h>
-
-#include <usb/usb.h>
-#include <usb/dev/dp.h>
-#include <usb/dev/request.h>
-#include <usb/hid/hid.h>
-#include <usb/dev/pipes.h>
-#include <usb/debug.h>
-#include <usb/hid/hidparser.h>
-#include <usb/classes/classes.h>
-#include <usb/hid/usages/core.h>
-#include <usb/hid/request.h>
-#include <usb/hid/hidreport.h>
-#include <usb/hid/usages/led.h>
-
-#include <usb/dev/driver.h>
-
-#include "kbddev.h"
-
-#include "conv.h"
-#include "kbdrepeat.h"
-
-#include "../usbhid.h"
-
-// FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
-
-/*----------------------------------------------------------------------------*/
-
-static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
-
-static const uint8_t ERROR_ROLLOVER = 1;
-
-/** Default idle rate for keyboards. */
-static const uint8_t IDLE_RATE = 0;
-
-/** Delay before a pressed key starts auto-repeating. */
-static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
-
-/** Delay between two repeats of a pressed key when auto-repeating. */
-static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
-
-/*----------------------------------------------------------------------------*/
-
-/** Keyboard polling endpoint description for boot protocol class. */
-usb_endpoint_description_t usb_hid_kbd_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
-};
-
-const char *HID_KBD_FUN_NAME = "keyboard";
-const char *HID_KBD_CLASS_NAME = "keyboard";
-
-static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
-
-/*----------------------------------------------------------------------------*/
-
-enum {
-	USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
-};
-
-static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
-    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
-        0x05, 0x01,  // Usage Page (Generic Desktop),
-        0x09, 0x06,  // Usage (Keyboard),
-        0xA1, 0x01,  // Collection (Application),
-        0x75, 0x01,  //   Report Size (1),
-        0x95, 0x08,  //   Report Count (8),       
-        0x05, 0x07,  //   Usage Page (Key Codes);
-        0x19, 0xE0,  //   Usage Minimum (224),
-        0x29, 0xE7,  //   Usage Maximum (231),
-        0x15, 0x00,  //   Logical Minimum (0),
-        0x25, 0x01,  //   Logical Maximum (1),
-        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
-	0x95, 0x01,  //   Report Count (1),
-        0x75, 0x08,  //   Report Size (8),
-        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
-        0x95, 0x05,  //   Report Count (5),
-        0x75, 0x01,  //   Report Size (1),
-        0x05, 0x08,  //   Usage Page (Page# for LEDs),
-        0x19, 0x01,  //   Usage Minimum (1),
-        0x29, 0x05,  //   Usage Maxmimum (5),
-        0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
-        0x95, 0x01,  //   Report Count (1),
-        0x75, 0x03,  //   Report Size (3),
-        0x91, 0x01,  //   Output (Constant),              ; LED report padding
-        0x95, 0x06,  //   Report Count (6),
-        0x75, 0x08,  //   Report Size (8),
-        0x15, 0x00,  //   Logical Minimum (0),
-        0x25, 0xff,  //   Logical Maximum (255),
-        0x05, 0x07,  //   Usage Page (Key Codes),
-        0x19, 0x00,  //   Usage Minimum (0),
-        0x29, 0xff,  //   Usage Maximum (255),
-        0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
-        0xC0           // End Collection
-
-};
-
-/*----------------------------------------------------------------------------*/
-
-typedef enum usb_kbd_flags {
-	USB_KBD_STATUS_UNINITIALIZED = 0,
-	USB_KBD_STATUS_INITIALIZED = 1,
-	USB_KBD_STATUS_TO_DESTROY = -1
-} usb_kbd_flags;
-
-/*----------------------------------------------------------------------------*/
-/* IPC method handler                                                         */
-/*----------------------------------------------------------------------------*/
-
-static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
-
-/**
- * Default handler for IPC methods not handled by DDF.
- *
- * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
- * assumes the caller is the console and thus it stores IPC phone to it for 
- * later use by the driver to notify about key events.
- *
- * @param fun Device function handling the call.
- * @param icallid Call id.
- * @param icall Call data.
- */
-static void default_connection_handler(ddf_fun_t *fun,
-    ipc_callid_t icallid, ipc_call_t *icall)
-{
-	sysarg_t method = IPC_GET_IMETHOD(*icall);
-	int callback;
-	
-	usb_kbd_t *kbd_dev = (usb_kbd_t *)fun->driver_data;
-	if (kbd_dev == NULL) {
-		usb_log_debug("default_connection_handler: "
-		    "Missing parameter.\n");
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
-	switch (method) {
-	case IPC_M_CONNECT_TO_ME:
-		callback = IPC_GET_ARG5(*icall);
-
-		if (kbd_dev->console_phone != -1) {
-			usb_log_debug("default_connection_handler: "
-			    "console phone already set\n");
-			async_answer_0(icallid, ELIMIT);
-			return;
-		}
-
-		kbd_dev->console_phone = callback;
-		
-		usb_log_debug("default_connection_handler: OK\n");
-		async_answer_0(icallid, EOK);
-		break;
-	case KBDEV_SET_IND:
-		kbd_dev->mods = IPC_GET_ARG1(*icall);
-		usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
-		async_answer_0(icallid, EOK);
-		break;
-	default:
-		usb_log_debug("default_connection_handler: Wrong function.\n");
-		async_answer_0(icallid, EINVAL);
-		break;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-/* Key processing functions                                                   */
-/*----------------------------------------------------------------------------*/
-/**
- * Handles turning of LED lights on and off.
- *
- * As with most other keyboards, the LED indicators in USB keyboards are
- * driven by software. When state of some modifier changes, the input server
- * will call us and tell us to update the LED state and what the new state
- * should be.
- *
- * This functions sets the LED lights according to current settings of modifiers
- * kept in the keyboard device structure.
- *
- * @param kbd_dev Keyboard device structure.
- */
-static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
-{
-	if (kbd_dev->output_size == 0) {
-		return;
-	}
-
-	/* Reset the LED data. */
-	memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t));
-	usb_log_debug("Creating output report:\n");
-
-	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
-	    hid_dev->report, NULL, kbd_dev->led_path, 
-	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
-	    USB_HID_REPORT_TYPE_OUTPUT);
-	
-	while (field != NULL) {
-		
-		if ((field->usage == USB_HID_LED_NUM_LOCK) 
-		    && (kbd_dev->mods & KM_NUM_LOCK)){
-			field->value = 1;
-		}
-
-		if ((field->usage == USB_HID_LED_CAPS_LOCK) 
-		    && (kbd_dev->mods & KM_CAPS_LOCK)){
-			field->value = 1;
-		}
-
-		if ((field->usage == USB_HID_LED_SCROLL_LOCK) 
-		    && (kbd_dev->mods & KM_SCROLL_LOCK)){
-			field->value = 1;
-		}
-		
-		field = usb_hid_report_get_sibling(hid_dev->report, field,
-		    kbd_dev->led_path,  
-	    	USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
-			USB_HID_REPORT_TYPE_OUTPUT);
-	}
-	
-	// TODO: what about the Report ID?
-	int rc = usb_hid_report_output_translate(hid_dev->report, 0,
-	    kbd_dev->output_buffer, kbd_dev->output_size);
-	
-	if (rc != EOK) {
-		usb_log_warning("Error translating LED output to output report"
-		    ".\n");
-		return;
-	}
-	
-	usb_log_debug("Output report buffer: %s\n", 
-	    usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
-	        0));
-	
-	usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe, 
-	    hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
-	    kbd_dev->output_buffer, kbd_dev->output_size);
-}
-
-/*----------------------------------------------------------------------------*/
-/** Send key event.
- *
- * @param kbd_dev Keyboard device structure.
- * @param type Type of the event (press / release). Recognized values:
- *             KEY_PRESS, KEY_RELEASE
- * @param key Key code
- */
-void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type, 
-    unsigned int key)
-{
-	usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
-	if (kbd_dev->console_phone < 0) {
-		usb_log_warning(
-		    "Connection to console not ready, key discarded.\n");
-		return;
-	}
-	
-	async_obsolete_msg_2(kbd_dev->console_phone, KBDEV_EVENT, type, key);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static inline int usb_kbd_is_lock(unsigned int key_code) 
-{
-	return (key_code == KC_NUM_LOCK
-	    || key_code == KC_SCROLL_LOCK
-	    || key_code == KC_CAPS_LOCK);
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Checks if some keys were pressed or released and generates key events.
- *
- * An event is created only when key is pressed or released. Besides handling
- * the events (usb_kbd_push_ev()), the auto-repeat fibril is notified about
- * key presses and releases (see usb_kbd_repeat_start() and 
- * usb_kbd_repeat_stop()).
- *
- * @param kbd_dev Keyboard device structure.
- * @param key_codes Parsed keyboard report - codes of currently pressed keys 
- *                  according to HID Usage Tables.
- * @param count Number of key codes in report (size of the report).
- *
- * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
- */
-static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
-    usb_kbd_t *kbd_dev)
-{
-	unsigned int key;
-	unsigned int i, j;
-	
-	/*
-	 * First of all, check if the kbd have reported phantom state.
-	 *
-	 * As there is no way to distinguish keys from modifiers, we do not have
-	 * a way to check that 'all keys report Error Rollover'. We thus check
-	 * if there is at least one such error and in such case we ignore the
-	 * whole input report.
-	 */
-	i = 0;
-	while (i < kbd_dev->key_count && kbd_dev->keys[i] != ERROR_ROLLOVER) {
-		++i;
-	}
-	if (i != kbd_dev->key_count) {
-		usb_log_debug("Phantom state occured.\n");
-		// phantom state, do nothing
-		return;
-	}
-	
-	/*
-	 * 1) Key releases
-	 */
-	for (j = 0; j < kbd_dev->key_count; ++j) {
-		// try to find the old key in the new key list
-		i = 0;
-		while (i < kbd_dev->key_count
-		    && kbd_dev->keys[i] != kbd_dev->keys_old[j]) {
-			++i;
-		}
-		
-		if (i == kbd_dev->key_count) {
-			// not found, i.e. the key was released
-			key = usbhid_parse_scancode(kbd_dev->keys_old[j]);
-			if (!usb_kbd_is_lock(key)) {
-				usb_kbd_repeat_stop(kbd_dev, key);
-			}
-			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
-			usb_log_debug2("Key released: %d\n", key);
-		} else {
-			// found, nothing happens
-		}
-	}
-	
-	/*
-	 * 1) Key presses
-	 */
-	for (i = 0; i < kbd_dev->key_count; ++i) {
-		// try to find the new key in the old key list
-		j = 0;
-		while (j < kbd_dev->key_count 
-		    && kbd_dev->keys_old[j] != kbd_dev->keys[i]) { 
-			++j;
-		}
-		
-		if (j == kbd_dev->key_count) {
-			// not found, i.e. new key pressed
-			key = usbhid_parse_scancode(kbd_dev->keys[i]);
-			usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
-			    kbd_dev->keys[i]);
-			if (!usb_kbd_is_lock(key)) {
-				usb_kbd_repeat_start(kbd_dev, key);
-			}
-			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
-		} else {
-			// found, nothing happens
-		}
-	}
-	
-	memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
-	
-	usb_log_debug2("New stored keys: ");
-	for (i = 0; i < kbd_dev->key_count; ++i) {
-		usb_log_debug2("%d ", kbd_dev->keys_old[i]);
-	}
-	usb_log_debug2("\n");
-}
-
-/*----------------------------------------------------------------------------*/
-/* General kbd functions                                                      */
-/*----------------------------------------------------------------------------*/
-/**
- * Processes data received from the device in form of report.
- *
- * This function uses the HID report parser to translate the data received from
- * the device into generic USB HID key codes and into generic modifiers bitmap.
- * The parser then calls the given callback (usb_kbd_process_keycodes()).
- *
- * @note Currently, only the boot protocol is supported.
- *
- * @param kbd_dev Keyboard device structure (must be initialized).
- * @param buffer Data from the keyboard (i.e. the report).
- * @param actual_size Size of the data from keyboard (report size) in bytes.
- *
- * @sa usb_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(),
- *     usb_hid_parse_report().
- */
-static void usb_kbd_process_data(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev,
-                                 uint8_t *buffer, size_t actual_size)
-{
-	assert(hid_dev->report != NULL);
-	assert(hid_dev != NULL);
-	assert(kbd_dev != NULL);
-
-	usb_log_debug("Calling usb_hid_parse_report() with "
-	    "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
-	
-	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
-
-	uint8_t report_id;
-	int rc = usb_hid_parse_report(hid_dev->report, buffer, actual_size, 
-	    &report_id);
-	
-	if (rc != EOK) {
-		usb_log_warning("Error in usb_hid_parse_report():"
-		    "%s\n", str_error(rc));
-	}
-	
-	usb_hid_report_path_set_report_id (path, report_id);
-	
-	// fill in the currently pressed keys
-	
-	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
-	    hid_dev->report, NULL, path, 
-	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    USB_HID_REPORT_TYPE_INPUT);
-	unsigned i = 0;
-	
-	while (field != NULL) {
-		usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
-		    field, field->value, field->usage);
-		
-		assert(i < kbd_dev->key_count);
-		
-		// save the key usage
-		if (field->value != 0) {
-			kbd_dev->keys[i] = field->usage;
-		}
-		else {
-			kbd_dev->keys[i] = 0;
-		}
-		usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
-		
-		++i;
-		field = usb_hid_report_get_sibling(hid_dev->report, field, path, 
-		    USB_HID_PATH_COMPARE_END 
-		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-		    USB_HID_REPORT_TYPE_INPUT);
-	}
-	
-	usb_hid_report_path_free(path);
-	
-	usb_kbd_check_key_changes(hid_dev, kbd_dev);
-}
-
-/*----------------------------------------------------------------------------*/
-/* HID/KBD structure manipulation                                             */
-/*----------------------------------------------------------------------------*/
-
-static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
-{
-	kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Creates a new USB/HID keyboard structure.
- *
- * The structure returned by this function is not initialized. Use 
- * usb_kbd_init() to initialize it prior to polling.
- *
- * @return New uninitialized structure for representing a USB/HID keyboard or
- *         NULL if not successful (memory error).
- */
-static usb_kbd_t *usb_kbd_new(void)
-{
-	usb_kbd_t *kbd_dev = 
-	    (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
-
-	if (kbd_dev == NULL) {
-		usb_log_fatal("No memory!\n");
-		return NULL;
-	}
-	
-	kbd_dev->console_phone = -1;
-	kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
-	
-	return kbd_dev;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_kbd_create_function(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
-{
-	assert(hid_dev != NULL);
-	assert(hid_dev->usb_dev != NULL);
-	assert(kbd_dev != NULL);
-	
-	/* Create the function exposed under /dev/devices. */
-	usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
-	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
-	    HID_KBD_FUN_NAME);
-	if (fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	/*
-	 * Store the initialized HID device and HID ops
-	 * to the DDF function.
-	 */
-	fun->ops = &kbd_dev->ops;
-	fun->driver_data = kbd_dev;
-
-	int rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	usb_log_debug("%s function created. Handle: %" PRIun "\n",
-	    HID_KBD_FUN_NAME, fun->handle);
-	
-	usb_log_debug("Adding DDF function to class %s...\n", 
-	    HID_KBD_CLASS_NAME);
-	rc = ddf_fun_add_to_class(fun, HID_KBD_CLASS_NAME);
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class %s: %s.\n",
-		    HID_KBD_CLASS_NAME, str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/* API functions                                                              */
-/*----------------------------------------------------------------------------*/
-/**
- * Initialization of the USB/HID keyboard structure.
- *
- * This functions initializes required structures from the device's descriptors.
- *
- * During initialization, the keyboard is switched into boot protocol, the idle
- * rate is set to 0 (infinity), resulting in the keyboard only reporting event
- * when a key is pressed or released. Finally, the LED lights are turned on 
- * according to the default setup of lock keys.
- *
- * @note By default, the keyboards is initialized with Num Lock turned on and 
- *       other locks turned off.
- *
- * @param kbd_dev Keyboard device structure to be initialized.
- * @param dev DDF device structure of the keyboard.
- *
- * @retval EOK if successful.
- * @retval EINVAL if some parameter is not given.
- * @return Other value inherited from function usbhid_dev_init().
- */
-int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
-{
-	usb_log_debug("Initializing HID/KBD structure...\n");
-	
-	if (hid_dev == NULL) {
-		usb_log_error("Failed to init keyboard structure: no structure"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	usb_kbd_t *kbd_dev = usb_kbd_new();
-	if (kbd_dev == NULL) {
-		usb_log_error("Error while creating USB/HID KBD device "
-		    "structure.\n");
-		return ENOMEM;  // TODO: some other code??
-	}
-
-	/* Store link to HID device */
-	kbd_dev->hid_dev = hid_dev;
-	
-	/*
-	 * TODO: make more general
-	 */
-	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
-	
-	usb_hid_report_path_set_report_id(path, 0);
-	
-	kbd_dev->key_count = usb_hid_report_size(
-	    hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT); 
-	usb_hid_report_path_free(path);
-	
-	usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
-	
-	kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
-	
-	if (kbd_dev->keys == NULL) {
-		usb_log_fatal("No memory!\n");
-		free(kbd_dev);
-		return ENOMEM;
-	}
-	
-	kbd_dev->keys_old = 
-		(int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
-	
-	if (kbd_dev->keys_old == NULL) {
-		usb_log_fatal("No memory!\n");
-		free(kbd_dev->keys);
-		free(kbd_dev);
-		return ENOMEM;
-	}
-	
-	/*
-	 * Output report
-	 */
-	kbd_dev->output_size = 0;
-	kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report, 
-	    &kbd_dev->output_size, 0);
-	if (kbd_dev->output_buffer == NULL) {
-		usb_log_warning("Error creating output report buffer.\n");
-		free(kbd_dev->keys);
-		return ENOMEM;
-	}
-	
-	usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
-	
-	kbd_dev->led_path = usb_hid_report_path();
-	usb_hid_report_path_append_item(
-	    kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
-	
-	kbd_dev->led_output_size = usb_hid_report_size(hid_dev->report, 
-	    0, USB_HID_REPORT_TYPE_OUTPUT);
-	
-	usb_log_debug("Output report size (in items): %zu\n", 
-	    kbd_dev->led_output_size);
-	
-	kbd_dev->led_data = (int32_t *)calloc(
-	    kbd_dev->led_output_size, sizeof(int32_t));
-	
-	if (kbd_dev->led_data == NULL) {
-		usb_log_warning("Error creating buffer for LED output report."
-		    "\n");
-		free(kbd_dev->keys);
-		usb_hid_report_output_free(kbd_dev->output_buffer);
-		free(kbd_dev);
-		return ENOMEM;
-	}
-	
-	/*
-	 * Modifiers and locks
-	 */
-	kbd_dev->modifiers = 0;
-	kbd_dev->mods = DEFAULT_ACTIVE_MODS;
-	kbd_dev->lock_keys = 0;
-	
-	/*
-	 * Autorepeat
-	 */
-	kbd_dev->repeat.key_new = 0;
-	kbd_dev->repeat.key_repeated = 0;
-	kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
-	kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
-	
-	kbd_dev->repeat_mtx = (fibril_mutex_t *)(
-	    malloc(sizeof(fibril_mutex_t)));
-	if (kbd_dev->repeat_mtx == NULL) {
-		usb_log_fatal("No memory!\n");
-		free(kbd_dev->keys);
-		usb_hid_report_output_free(kbd_dev->output_buffer);
-		free(kbd_dev);
-		return ENOMEM;
-	}
-	
-	fibril_mutex_initialize(kbd_dev->repeat_mtx);
-	
-	// save the KBD device structure into the HID device structure
-	*data = kbd_dev;
-	
-	// set handler for incoming calls
-	kbd_dev->ops.default_handler = default_connection_handler;
-	
-	/*
-	 * Set LEDs according to initial setup.
-	 * Set Idle rate
-	 */
-	usb_kbd_set_led(hid_dev, kbd_dev);
-	
-	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
-	    hid_dev->usb_dev->interface_no, IDLE_RATE);
-	
-	/*
-	 * Create new fibril for auto-repeat
-	 */
-	fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
-	if (fid == 0) {
-		usb_log_error("Failed to start fibril for KBD auto-repeat");
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-	
-	kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
-	usb_log_debug("HID/KBD device structure initialized.\n");
-	
-	usb_log_debug("Creating KBD function...\n");
-	int rc = usb_kbd_create_function(hid_dev, kbd_dev);
-	if (rc != EOK) {
-		usb_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data, 
-     uint8_t *buffer, size_t buffer_size)
-{
-	if (hid_dev == NULL || buffer == NULL || data == NULL) {
-		// do not continue polling (???)
-		return false;
-	}
-	
-	usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
-	assert(kbd_dev != NULL);
-	
-	// TODO: add return value from this function
-	usb_kbd_process_data(hid_dev, kbd_dev, buffer, buffer_size);
-	
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
-{
-	return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
-{
-	return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Properly destroys the USB/HID keyboard structure.
- *
- * @param kbd_dev Pointer to the structure to be destroyed.
- */
-void usb_kbd_free(usb_kbd_t **kbd_dev)
-{
-	if (kbd_dev == NULL || *kbd_dev == NULL) {
-		return;
-	}
-	
-	// hangup phone to the console
-	async_obsolete_hangup((*kbd_dev)->console_phone);
-	
-	if ((*kbd_dev)->repeat_mtx != NULL) {
-		//assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
-		while (fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)) {}
-		free((*kbd_dev)->repeat_mtx);
-	}
-	
-	// free all buffers
-	if ((*kbd_dev)->keys != NULL) {
-		free((*kbd_dev)->keys);
-	}
-	if ((*kbd_dev)->keys_old != NULL) {
-		free((*kbd_dev)->keys_old);
-	}
-	if ((*kbd_dev)->led_data != NULL) {
-		free((*kbd_dev)->led_data);
-	}
-	if ((*kbd_dev)->led_path != NULL) {
-		usb_hid_report_path_free((*kbd_dev)->led_path);
-	}
-	if ((*kbd_dev)->output_buffer != NULL) {
-		usb_hid_report_output_free((*kbd_dev)->output_buffer);
-	}
-
-	free(*kbd_dev);
-	*kbd_dev = NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
-{
-	if (hid_dev == NULL) {
-		return;
-	}
-	
-	if (data != NULL) {
-		usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
-		if (usb_kbd_is_initialized(kbd_dev)) {
-			usb_kbd_mark_unusable(kbd_dev);
-		} else {
-			usb_kbd_free(&kbd_dev);
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
-{
-	int rc = usb_hid_parse_report_descriptor(hid_dev->report, 
-	    USB_KBD_BOOT_REPORT_DESCRIPTOR, 
-	    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to parse boot report descriptor: %s\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
-	    hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
-	
-	if (rc != EOK) {
-		usb_log_warning("Failed to set boot protocol to the device: "
-		    "%s\n", str_error(rc));
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/kbd/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,147 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB HID keyboard device structure and API.
- */
-
-#ifndef USB_HID_KBDDEV_H_
-#define USB_HID_KBDDEV_H_
-
-#include <stdint.h>
-
-#include <fibril_synch.h>
-
-#include <usb/hid/hid.h>
-#include <usb/hid/hidparser.h>
-#include <ddf/driver.h>
-#include <usb/dev/pipes.h>
-#include <usb/dev/driver.h>
-
-#include "kbdrepeat.h"
-
-struct usb_hid_dev;
-
-/*----------------------------------------------------------------------------*/
-/**
- * USB/HID keyboard device type.
- *
- * Holds a reference to generic USB/HID device structure and keyboard-specific
- * data, such as currently pressed keys, modifiers and lock keys.
- *
- * Also holds a IPC phone to the console (since there is now no other way to 
- * communicate with it).
- *
- * @note Storing active lock keys in this structure results in their setting
- *       being device-specific.
- */
-typedef struct usb_kbd_t {
-	/** Link to HID device structure */
-	struct usb_hid_dev *hid_dev;
-
-	/** Previously pressed keys (not translated to key codes). */
-	int32_t *keys_old;
-	/** Currently pressed keys (not translated to key codes). */
-	int32_t *keys;
-	/** Count of stored keys (i.e. number of keys in the report). */
-	size_t key_count;
-	/** Currently pressed modifiers (bitmap). */
-	uint8_t modifiers;
-	
-	/** Currently active modifiers including locks. Sent to the console. */
-	unsigned mods;
-	
-	/** Currently active lock keys. */
-	unsigned lock_keys;
-	
-	/** IPC phone to the console device (for sending key events). */
-	int console_phone;
-	
-	/** @todo What is this actually? */
-	ddf_dev_ops_t ops;
-	
-	/** Information for auto-repeat of keys. */
-	usb_kbd_repeat_t repeat;
-	
-	/** Mutex for accessing the information about auto-repeat. */
-	fibril_mutex_t *repeat_mtx;
-	
-	uint8_t *output_buffer;
-	
-	size_t output_size;
-	
-	size_t led_output_size;
-	
-	usb_hid_report_path_t *led_path;
-	
-	int32_t *led_data;
-	
-	/** State of the structure (for checking before use). 
-	 * 
-	 * 0 - not initialized
-	 * 1 - initialized
-	 * -1 - ready for destroying
-	 */
-	int initialized;
-} usb_kbd_t;
-
-/*----------------------------------------------------------------------------*/
-
-usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
-
-const char *HID_KBD_FUN_NAME;
-const char *HID_KBD_CLASS_NAME;
-
-/*----------------------------------------------------------------------------*/
-
-int usb_kbd_init(struct usb_hid_dev *hid_dev, void **data);
-
-bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, void *data, 
-                              uint8_t *buffer, size_t buffer_size);
-
-int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
-
-int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev);
-
-void usb_kbd_free(usb_kbd_t **kbd_dev);
-
-void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
-    int type, unsigned int key);
-
-void usb_kbd_deinit(struct usb_hid_dev *hid_dev, void *data);
-
-int usb_kbd_set_boot_protocol(struct usb_hid_dev *hid_dev);
-
-#endif /* USB_HID_KBDDEV_H_ */
-
-/**
- * @}
- */
Index: pace/drv/usbhid/kbd/kbdrepeat.c
===================================================================
--- uspace/drv/usbhid/kbd/kbdrepeat.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,186 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/**
- * @file
- * USB HID keyboard autorepeat facilities
- */
-
-#include <fibril_synch.h>
-#include <io/keycode.h>
-#include <io/console.h>
-#include <errno.h>
-
-#include <usb/debug.h>
-
-#include "kbdrepeat.h"
-#include "kbddev.h"
-
-
-/** Delay between auto-repeat state checks when no key is being repeated. */
-static unsigned int CHECK_DELAY = 10000;
-
-/*----------------------------------------------------------------------------*/
-/**
- * Main loop handling the auto-repeat of keys.
- *
- * This functions periodically checks if there is some key to be auto-repeated.
- *
- * If a new key is to be repeated, it uses the delay before first repeat stored
- * in the keyboard structure to wait until the key has to start repeating.
- *
- * If the same key is still pressed, it uses the delay between repeats stored
- * in the keyboard structure to wait until the key should be repeated.
- * 
- * If the currently repeated key is not pressed any more (
- * usb_kbd_repeat_stop() was called), it stops repeating it and starts 
- * checking again.
- *
- * @note For accessing the keyboard device auto-repeat information a fibril
- *       mutex (repeat_mtx) from the @a kbd structure is used.
- * 
- * @param kbd Keyboard device structure.
- */
-static void usb_kbd_repeat_loop(usb_kbd_t *kbd)
-{
-	unsigned int delay = 0;
-	
-	usb_log_debug("Starting autorepeat loop.\n");
-
-	while (true) {
-		// check if the kbd structure is usable
-		if (!usb_kbd_is_initialized(kbd)) {
-			if (usb_kbd_is_ready_to_destroy(kbd)) {
-				usb_kbd_free(&kbd);
-				assert(kbd == NULL);
-			}
-			return;
-		}
-		
-		fibril_mutex_lock(kbd->repeat_mtx);
-
-		if (kbd->repeat.key_new > 0) {
-			if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
-				usb_log_debug2("Repeating key: %u.\n", 
-				    kbd->repeat.key_repeated);
-				// ugly hack with the NULL
-				usb_kbd_push_ev(NULL, kbd, KEY_PRESS, 
-				    kbd->repeat.key_repeated);
-				delay = kbd->repeat.delay_between;
-			} else {
-				usb_log_debug("New key to repeat: %u.\n", 
-				    kbd->repeat.key_new);
-				kbd->repeat.key_repeated = kbd->repeat.key_new;
-				delay = kbd->repeat.delay_before;
-			}
-		} else {
-			if (kbd->repeat.key_repeated > 0) {
-				usb_log_debug("Stopping to repeat key: %u.\n", 
-				    kbd->repeat.key_repeated);
-				kbd->repeat.key_repeated = 0;
-			}
-			delay = CHECK_DELAY;
-		}
-		fibril_mutex_unlock(kbd->repeat_mtx);
-		
-		async_usleep(delay);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Main routine to be executed by a fibril for handling auto-repeat.
- *
- * Starts the loop for checking changes in auto-repeat.
- * 
- * @param arg User-specified argument. Expects pointer to the keyboard device
- *            structure representing the keyboard.
- *
- * @retval EOK if the routine has finished.
- * @retval EINVAL if no argument is supplied.
- */
-int usb_kbd_repeat_fibril(void *arg)
-{
-	usb_log_debug("Autorepeat fibril spawned.\n");
-	
-	if (arg == NULL) {
-		usb_log_error("No device!\n");
-		return EINVAL;
-	}
-	
-	usb_kbd_t *kbd = (usb_kbd_t *)arg;
-	
-	usb_kbd_repeat_loop(kbd);
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Start repeating particular key.
- *
- * @note Only one key is repeated at any time, so calling this function 
- *       effectively cancels auto-repeat of the current repeated key (if any)
- *       and 'schedules' another key for auto-repeat.
- *
- * @param kbd Keyboard device structure.
- * @param key Key to start repeating.
- */
-void usb_kbd_repeat_start(usb_kbd_t *kbd, unsigned int key)
-{
-	fibril_mutex_lock(kbd->repeat_mtx);
-	kbd->repeat.key_new = key;
-	fibril_mutex_unlock(kbd->repeat_mtx);
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Stop repeating particular key.
- *
- * @note Only one key is repeated at any time, but this function may be called
- *       even with key that is not currently repeated (in that case nothing 
- *       happens).
- *
- * @param kbd Keyboard device structure.
- * @param key Key to stop repeating.
- */
-void usb_kbd_repeat_stop(usb_kbd_t *kbd, unsigned int key)
-{
-	fibril_mutex_lock(kbd->repeat_mtx);
-	if (key == kbd->repeat.key_new) {
-		kbd->repeat.key_new = 0;
-	}
-	fibril_mutex_unlock(kbd->repeat_mtx);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/kbd/kbdrepeat.h
===================================================================
--- uspace/drv/usbhid/kbd/kbdrepeat.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,68 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB HID keyboard autorepeat facilities
- */
-
-#ifndef USB_HID_KBDREPEAT_H_
-#define USB_HID_KBDREPEAT_H_
-
-struct usb_kbd_t;
-
-/*----------------------------------------------------------------------------*/
-/**
- * Structure for keeping information needed for auto-repeat of keys.
- */
-typedef struct {
-	/** Last pressed key. */
-	unsigned int key_new;
-	/** Key to be repeated. */
-	unsigned int key_repeated;
-	/** Delay before first repeat in microseconds. */
-	unsigned int delay_before;
-	/** Delay between repeats in microseconds. */
-	unsigned int delay_between;
-} usb_kbd_repeat_t;
-
-/*----------------------------------------------------------------------------*/
-
-int usb_kbd_repeat_fibril(void *arg);
-
-void usb_kbd_repeat_start(struct usb_kbd_t *kbd, unsigned int key);
-
-void usb_kbd_repeat_stop(struct usb_kbd_t *kbd, unsigned int key);
-
-#endif /* USB_HID_KBDREPEAT_H_ */
-
-/**
- * @}
- */
Index: pace/drv/usbhid/kbd/main.c
===================================================================
--- uspace/drv/usbhid/kbd/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,244 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/**
- * @file
- * Main routines of USB KBD driver.
- */
-
-#include <ddf/driver.h>
-#include <usb/debug.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/dev/driver.h>
-
-#include "kbddev.h"
-#include "kbdrepeat.h"
-
-/*----------------------------------------------------------------------------*/
-
-#define NAME "usbkbd"
-
-/**
- * Function for adding a new device of type USB/HID/keyboard.
- *
- * This functions initializes required structures from the device's descriptors
- * and starts new fibril for polling the keyboard for events and another one for
- * handling auto-repeat of keys.
- *
- * During initialization, the keyboard is switched into boot protocol, the idle
- * rate is set to 0 (infinity), resulting in the keyboard only reporting event
- * when a key is pressed or released. Finally, the LED lights are turned on 
- * according to the default setup of lock keys.
- *
- * @note By default, the keyboards is initialized with Num Lock turned on and 
- *       other locks turned off.
- * @note Currently supports only boot-protocol keyboards.
- *
- * @param dev Device to add.
- *
- * @retval EOK if successful.
- * @retval ENOMEM if there
- * @return Other error code inherited from one of functions usb_kbd_init(),
- *         ddf_fun_bind() and ddf_fun_add_to_class().
- *
- * @sa usb_kbd_fibril(), usb_kbd_repeat_fibril()
- */
-static int usb_kbd_try_add_device(usb_device_t *dev)
-{
-	/* Create the function exposed under /dev/devices. */
-	ddf_fun_t *kbd_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 
-	    "keyboard");
-	if (kbd_fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	/* 
-	 * Initialize device (get and process descriptors, get address, etc.)
-	 */
-	usb_log_debug("Initializing USB/HID KBD device...\n");
-	
-	usb_kbd_t *kbd_dev = usb_kbd_new();
-	if (kbd_dev == NULL) {
-		usb_log_error("Error while creating USB/HID KBD device "
-		    "structure.\n");
-		ddf_fun_destroy(kbd_fun);
-		return ENOMEM;  // TODO: some other code??
-	}
-	
-	int rc = usb_kbd_init(kbd_dev, dev);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize USB/HID KBD device.\n");
-		ddf_fun_destroy(kbd_fun);
-		usb_kbd_free(&kbd_dev);
-		return rc;
-	}	
-	
-	usb_log_debug("USB/HID KBD device structure initialized.\n");
-	
-	/*
-	 * Store the initialized keyboard device and keyboard ops
-	 * to the DDF function.
-	 */
-	kbd_fun->driver_data = kbd_dev;
-	kbd_fun->ops = &keyboard_ops;
-
-	rc = ddf_fun_bind(kbd_fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(kbd_fun);
-		usb_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class 'keyboard': %s.\n",
-		    str_error(rc));
-		ddf_fun_destroy(kbd_fun);
-		usb_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	/* Start automated polling function.
-	 * This will create a separate fibril that will query the device
-	 * for the data continuously 
-	 */
-       rc = usb_device_auto_poll(dev,
-	   /* Index of the polling pipe. */
-	   USB_KBD_POLL_EP_NO,
-	   /* Callback when data arrives. */
-	   usb_kbd_polling_callback,
-	   /* How much data to request. */
-	   dev->pipes[USB_KBD_POLL_EP_NO].pipe->max_packet_size,
-	   /* Callback when the polling ends. */
-	   usb_kbd_polling_ended_callback,
-	   /* Custom argument. */
-	   kbd_dev);
-	
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to start polling fibril for `%s'.\n",
-		    dev->ddf_dev->name);
-		return rc;
-	}
-	
-	/*
-	 * Create new fibril for auto-repeat
-	 */
-	fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
-	if (fid == 0) {
-		usb_log_error("Failed to start fibril for KBD auto-repeat");
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-
-	(void)keyboard_ops;
-
-	/*
-	 * Hurrah, device is initialized.
-	 */
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Callback for passing a new device to the driver.
- *
- * @note Currently, only boot-protocol keyboards are supported by this driver.
- *
- * @param dev Structure representing the new device.
- *
- * @retval EOK if successful. 
- * @retval EREFUSED if the device is not supported.
- */
-static int usb_kbd_add_device(usb_device_t *dev)
-{
-	usb_log_debug("usb_kbd_add_device()\n");
-	
-	if (dev->interface_no < 0) {
-		usb_log_warning("Device is not a supported keyboard.\n");
-		usb_log_error("Failed to add USB KBD device: endpoint not "
-		    "found.\n");
-		return ENOTSUP;
-	}
-	
-	int rc = usb_kbd_try_add_device(dev);
-	
-	if (rc != EOK) {
-		usb_log_warning("Device is not a supported keyboard.\n");
-		usb_log_error("Failed to add KBD device: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	usb_log_info("Keyboard `%s' ready to use.\n", dev->ddf_dev->name);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/* Currently, the framework supports only device adding. Once the framework
- * supports unplug, more callbacks will be added. */
-static usb_driver_ops_t usb_kbd_driver_ops = {
-        .add_device = usb_kbd_add_device,
-};
-
-
-/* The driver itself. */
-static usb_driver_t usb_kbd_driver = {
-        .name = NAME,
-        .ops = &usb_kbd_driver_ops,
-        .endpoints = usb_kbd_endpoints
-};
-
-/*----------------------------------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS USB KBD driver.\n");
-
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
-
-	return usb_driver_main(&usb_kbd_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,211 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/**
- * @file
- * Main routines of USB HID driver.
- */
-
-#include <ddf/driver.h>
-#include <usb/debug.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/dev/driver.h>
-#include <usb/dev/poll.h>
-
-#include "usbhid.h"
-
-/*----------------------------------------------------------------------------*/
-
-#define NAME "usbhid"
-
-/**
- * Function for adding a new device of type USB/HID/keyboard.
- *
- * This functions initializes required structures from the device's descriptors
- * and starts new fibril for polling the keyboard for events and another one for
- * handling auto-repeat of keys.
- *
- * During initialization, the keyboard is switched into boot protocol, the idle
- * rate is set to 0 (infinity), resulting in the keyboard only reporting event
- * when a key is pressed or released. Finally, the LED lights are turned on 
- * according to the default setup of lock keys.
- *
- * @note By default, the keyboards is initialized with Num Lock turned on and 
- *       other locks turned off.
- * @note Currently supports only boot-protocol keyboards.
- *
- * @param dev Device to add.
- *
- * @retval EOK if successful.
- * @retval ENOMEM if there
- * @return Other error code inherited from one of functions usb_kbd_init(),
- *         ddf_fun_bind() and ddf_fun_add_to_class().
- */
-static int usb_hid_try_add_device(usb_device_t *dev)
-{
-	assert(dev != NULL);
-	
-	/* 
-	 * Initialize device (get and process descriptors, get address, etc.)
-	 */
-	usb_log_debug("Initializing USB/HID device...\n");
-	
-	usb_hid_dev_t *hid_dev = usb_hid_new();
-	if (hid_dev == NULL) {
-		usb_log_error("Error while creating USB/HID device "
-		    "structure.\n");
-		return ENOMEM;
-	}
-	
-	int rc = usb_hid_init(hid_dev, dev);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize USB/HID device.\n");
-		usb_hid_free(&hid_dev);
-		return rc;
-	}	
-	
-	usb_log_debug("USB/HID device structure initialized.\n");
-	
-	/*
-	 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
-	 *    do nej.
-	 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 
-	 *    vyplnenu strukturu usbhid_iface_t.
-	 * 3) klientska aplikacia - musi si rucne vytvorit telefon
-	 *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 
-	 *    k tej fcii.
-	 *    pouzit usb/classes/hid/iface.h - prvy int je telefon
-	 */
-	
-	/* Start automated polling function.
-	 * This will create a separate fibril that will query the device
-	 * for the data continuously 
-	 */
-       rc = usb_device_auto_poll(dev,
-	   /* Index of the polling pipe. */
-	   hid_dev->poll_pipe_index,
-	   /* Callback when data arrives. */
-	   usb_hid_polling_callback,
-	   /* How much data to request. */
-	   dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
-	   /* Callback when the polling ends. */
-	   usb_hid_polling_ended_callback,
-	   /* Custom argument. */
-	   hid_dev);
-	
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to start polling fibril for `%s'.\n",
-		    dev->ddf_dev->name);
-		return rc;
-	}
-
-	/*
-	 * Hurrah, device is initialized.
-	 */
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Callback for passing a new device to the driver.
- *
- * @note Currently, only boot-protocol keyboards are supported by this driver.
- *
- * @param dev Structure representing the new device.
- *
- * @retval EOK if successful. 
- * @retval EREFUSED if the device is not supported.
- */
-static int usb_hid_add_device(usb_device_t *dev)
-{
-	usb_log_debug("usb_hid_add_device()\n");
-	
-	if (dev == NULL) {
-		usb_log_warning("Wrong parameter given for add_device().\n");
-		return EINVAL;
-	}
-	
-	if (dev->interface_no < 0) {
-		usb_log_warning("Device is not a supported HID device.\n");
-		usb_log_error("Failed to add HID device: endpoints not found."
-		    "\n");
-		return ENOTSUP;
-	}
-	
-	int rc = usb_hid_try_add_device(dev);
-	
-	if (rc != EOK) {
-		usb_log_warning("Device is not a supported HID device.\n");
-		usb_log_error("Failed to add HID device: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/* Currently, the framework supports only device adding. Once the framework
- * supports unplug, more callbacks will be added. */
-static usb_driver_ops_t usb_hid_driver_ops = {
-        .add_device = usb_hid_add_device,
-};
-
-
-/* The driver itself. */
-static usb_driver_t usb_hid_driver = {
-        .name = NAME,
-        .ops = &usb_hid_driver_ops,
-        .endpoints = usb_hid_endpoints
-};
-
-/*----------------------------------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS USB HID driver.\n");
-
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-
-	return usb_driver_main(&usb_hid_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,567 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/**
- * @file
- * USB Mouse driver API.
- */
-
-#include <usb/debug.h>
-#include <usb/classes/classes.h>
-#include <usb/hid/hid.h>
-#include <usb/hid/request.h>
-#include <usb/hid/usages/core.h>
-#include <errno.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <str_error.h>
-#include <ipc/mouse.h>
-#include <io/console.h>
-
-#include <ipc/kbdev.h>
-#include <io/keycode.h>
-
-#include "mousedev.h"
-#include "../usbhid.h"
-
-// FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
-
-#define NAME "mouse"
-
-/*----------------------------------------------------------------------------*/
-
-usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
-	.transfer_type = USB_TRANSFER_INTERRUPT,
-	.direction = USB_DIRECTION_IN,
-	.interface_class = USB_CLASS_HID,
-	.interface_subclass = USB_HID_SUBCLASS_BOOT,
-	.interface_protocol = USB_HID_PROTOCOL_MOUSE,
-	.flags = 0
-};
-
-const char *HID_MOUSE_FUN_NAME = "mouse";
-const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
-const char *HID_MOUSE_CLASS_NAME = "mouse";
-const char *HID_MOUSE_WHEEL_CLASS_NAME = "keyboard";
-
-/** Default idle rate for mouses. */
-static const uint8_t IDLE_RATE = 0;
-static const size_t USB_MOUSE_BUTTON_COUNT = 3;
-
-/*----------------------------------------------------------------------------*/
-
-enum {
-	USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63
-};
-
-static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[
-    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = {
-	0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
-	0x09, 0x02,                    // USAGE (Mouse)
-	0xa1, 0x01,                    // COLLECTION (Application)
-	0x09, 0x01,                    //   USAGE (Pointer)
-	0xa1, 0x00,                    //   COLLECTION (Physical)
-	0x95, 0x03,                    //     REPORT_COUNT (3)
-	0x75, 0x01,                    //     REPORT_SIZE (1)
-	0x05, 0x09,                    //     USAGE_PAGE (Button)
-	0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
-	0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
-	0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
-	0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
-	0x81, 0x02,                    //     INPUT (Data,Var,Abs)
-	0x95, 0x01,                    //     REPORT_COUNT (1)
-	0x75, 0x05,                    //     REPORT_SIZE (5)
-	0x81, 0x01,                    //     INPUT (Cnst)
-	0x75, 0x08,                    //     REPORT_SIZE (8)
-	0x95, 0x02,                    //     REPORT_COUNT (2)
-	0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
-	0x09, 0x30,                    //     USAGE (X)
-	0x09, 0x31,                    //     USAGE (Y)
-	0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
-	0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
-	0x81, 0x06,                    //     INPUT (Data,Var,Rel)
-	0xc0,                          //   END_COLLECTION
-	0xc0                           // END_COLLECTION
-};
-
-/*----------------------------------------------------------------------------*/
-
-/** Default handler for IPC methods not handled by DDF.
- *
- * @param fun Device function handling the call.
- * @param icallid Call id.
- * @param icall Call data.
- */
-static void default_connection_handler(ddf_fun_t *fun,
-    ipc_callid_t icallid, ipc_call_t *icall)
-{
-	sysarg_t method = IPC_GET_IMETHOD(*icall);
-	
-	usb_mouse_t *mouse_dev = (usb_mouse_t *)fun->driver_data;
-	
-	if (mouse_dev == NULL) {
-		usb_log_debug("default_connection_handler: Missing "
-		    "parameters.\n");
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-	
-	usb_log_debug("default_connection_handler: fun->name: %s\n",
-	              fun->name);
-	usb_log_debug("default_connection_handler: mouse_phone: %d, wheel "
-	    "phone: %d\n", mouse_dev->mouse_phone, mouse_dev->wheel_phone);
-	
-	int *phone = (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) 
-		     ? &mouse_dev->mouse_phone : &mouse_dev->wheel_phone;
-	
-	if (method == IPC_M_CONNECT_TO_ME) {
-		int callback = IPC_GET_ARG5(*icall);
-
-		if (*phone != -1) {
-			usb_log_debug("default_connection_handler: Console "
-			    "phone to mouse already set.\n");
-			async_answer_0(icallid, ELIMIT);
-			return;
-		}
-
-		*phone = callback;
-		usb_log_debug("Console phone to mouse set ok (%d).\n", *phone);
-		async_answer_0(icallid, EOK);
-		return;
-	}
-
-	usb_log_debug("default_connection_handler: Invalid function.\n");
-	async_answer_0(icallid, EINVAL);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static usb_mouse_t *usb_mouse_new(void)
-{
-	usb_mouse_t *mouse = calloc(1, sizeof(usb_mouse_t));
-	if (mouse == NULL) {
-		return NULL;
-	}
-	mouse->mouse_phone = -1;
-	mouse->wheel_phone = -1;
-	
-	return mouse;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void usb_mouse_free(usb_mouse_t **mouse_dev)
-{
-	assert(mouse_dev != NULL && *mouse_dev != NULL);
-	
-	// hangup phone to the console
-	if ((*mouse_dev)->mouse_phone >= 0) {
-		async_obsolete_hangup((*mouse_dev)->mouse_phone);
-	}
-	
-	if ((*mouse_dev)->wheel_phone >= 0) {
-		async_obsolete_hangup((*mouse_dev)->wheel_phone);
-	}
-	
-	free(*mouse_dev);
-	*mouse_dev = NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
-{
-	kbd_event_t ev;
-	
-	ev.type = KEY_PRESS;
-	ev.key = (wheel > 0) ? KC_UP : (wheel < 0) ? KC_DOWN : 0;
-	ev.mods = 0;
-	ev.c = 0;
-
-	if (mouse_dev->wheel_phone < 0) {
-		usb_log_warning(
-		    "Connection to console not ready, key discarded.\n");
-		return;
-	}
-	
-	int count = (wheel < 0) ? -wheel : wheel;
-	int i;
-	
-	for (i = 0; i < count * 3; ++i) {
-		usb_log_debug2("Sending key %d to the console\n", ev.key);
-		async_obsolete_msg_4(mouse_dev->wheel_phone, KBDEV_EVENT, ev.type, 
-		    ev.key, ev.mods, ev.c);
-		// send key release right away
-		async_obsolete_msg_4(mouse_dev->wheel_phone, KBDEV_EVENT, KEY_RELEASE, 
-		    ev.key, ev.mods, ev.c);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev, 
-                                     usb_mouse_t *mouse_dev, uint8_t *buffer,
-                                     size_t buffer_size)
-{
-	assert(mouse_dev != NULL);
-	
-	usb_log_debug2("got buffer: %s.\n",
-	    usb_debug_str_buffer(buffer, buffer_size, 0));
-	
-	if (mouse_dev->mouse_phone < 0) {
-		usb_log_warning(NAME " No console phone.\n");
-		return true;
-	}
-
-	/*
-	 * parse the input report
-	 */
-	
-	usb_log_debug(NAME " Calling usb_hid_parse_report() with "
-	    "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0));
-	
-	uint8_t report_id;
-	
-	int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 
-	    &report_id);
-	
-	if (rc != EOK) {
-		usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n", 
-		    str_error(rc));
-		return true;
-	}
-	
-	/*
-	 * X
-	 */
-	int shift_x = 0;
-	
-	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 
-	    USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
-
-	usb_hid_report_path_set_report_id(path, report_id);
-
-	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
-	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 
-	    USB_HID_REPORT_TYPE_INPUT);
-
-	if (field != NULL) {
-		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
-		    field->usage);
-		shift_x = field->value;
-	}
-
-	usb_hid_report_path_free(path);
-	
-	/*
-	 * Y
-	 */
-	int shift_y = 0;
-	
-	path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 
-	    USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
-
-	usb_hid_report_path_set_report_id(path, report_id);
-
-	field = usb_hid_report_get_sibling(
-	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 
-	    USB_HID_REPORT_TYPE_INPUT);
-
-	if (field != NULL) {
-		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
-		    field->usage);
-		shift_y = field->value;
-	}
-
-	usb_hid_report_path_free(path);
-	
-	if ((shift_x != 0) || (shift_y != 0)) {
-		async_obsolete_req_2_0(mouse_dev->mouse_phone,
-		    MEVENT_MOVE, shift_x, shift_y);
-	}
-	
-	/*
-	 * Wheel
-	 */
-	int wheel = 0;
-	
-	path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 
-	    USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
-
-	usb_hid_report_path_set_report_id(path, report_id);
-	
-	field = usb_hid_report_get_sibling(
-	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 
-	    USB_HID_REPORT_TYPE_INPUT);
-
-	if (field != NULL) {
-		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
-		    field->usage);
-		wheel = field->value;
-	}
-
-	usb_hid_report_path_free(path);
-	
-	// send arrow up for positive direction and arrow down for negative
-	// direction; three arrows for difference of 1
-	usb_mouse_send_wheel(mouse_dev, wheel);
-	
-	
-	/*
-	 * Buttons
-	 */
-	path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
-	usb_hid_report_path_set_report_id(path, report_id);
-	
-	field = usb_hid_report_get_sibling(
-	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
-	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    USB_HID_REPORT_TYPE_INPUT);
-
-	while (field != NULL) {
-		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
-		    field->usage);
-		
-		if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
-		    && field->value != 0) {
-			async_obsolete_req_2_0(mouse_dev->mouse_phone,
-			    MEVENT_BUTTON, field->usage, 1);
-			mouse_dev->buttons[field->usage - field->usage_minimum]
-			    = field->value;
-		} else if (
-		    mouse_dev->buttons[field->usage - field->usage_minimum] != 0
-		    && field->value == 0) {
-		       async_obsolete_req_2_0(mouse_dev->mouse_phone,
-			   MEVENT_BUTTON, field->usage, 0);
-		       mouse_dev->buttons[field->usage - field->usage_minimum]
-			   = field->value;
-	       }
-		
-		field = usb_hid_report_get_sibling(
-		    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
-		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-		    USB_HID_REPORT_TYPE_INPUT);
-	}
-	
-	usb_hid_report_path_free(path);
-
-	return true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
-{
-	assert(hid_dev != NULL);
-	assert(mouse != NULL);
-	
-	/* Create the function exposed under /dev/devices. */
-	usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
-	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
-	    HID_MOUSE_FUN_NAME);
-	if (fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	fun->ops = &mouse->ops;
-	fun->driver_data = mouse;
-
-	int rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	usb_log_debug("Adding DDF function to class %s...\n", 
-	    HID_MOUSE_CLASS_NAME);
-	rc = ddf_fun_add_to_class(fun, HID_MOUSE_CLASS_NAME);
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class %s: %s.\n",
-		    HID_MOUSE_CLASS_NAME, str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	/*
-	 * Special function for acting as keyboard (wheel)
-	 */
-	usb_log_debug("Creating DDF function %s...\n", 
-	              HID_MOUSE_WHEEL_FUN_NAME);
-	fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
-	    HID_MOUSE_WHEEL_FUN_NAME);
-	if (fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	/*
-	 * Store the initialized HID device and HID ops
-	 * to the DDF function.
-	 */
-	fun->ops = &mouse->ops;
-	fun->driver_data = mouse;
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	usb_log_debug("Adding DDF function to class %s...\n", 
-	    HID_MOUSE_WHEEL_CLASS_NAME);
-	rc = ddf_fun_add_to_class(fun, HID_MOUSE_WHEEL_CLASS_NAME);
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class %s: %s.\n",
-		    HID_MOUSE_WHEEL_CLASS_NAME, str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
-{
-	usb_log_debug("Initializing HID/Mouse structure...\n");
-	
-	if (hid_dev == NULL) {
-		usb_log_error("Failed to init keyboard structure: no structure"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	usb_mouse_t *mouse_dev = usb_mouse_new();
-	if (mouse_dev == NULL) {
-		usb_log_error("Error while creating USB/HID Mouse device "
-		    "structure.\n");
-		return ENOMEM;
-	}
-	
-	mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT, 
-	    sizeof(int32_t));
-	
-	if (mouse_dev->buttons == NULL) {
-		usb_log_fatal("No memory!\n");
-		free(mouse_dev);
-		return ENOMEM;
-	}
-	
-	// save the Mouse device structure into the HID device structure
-	*data = mouse_dev;
-	
-	// set handler for incoming calls
-	mouse_dev->ops.default_handler = default_connection_handler;
-	
-	// TODO: how to know if the device supports the request???
-	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
-	    hid_dev->usb_dev->interface_no, IDLE_RATE);
-	
-	int rc = usb_mouse_create_function(hid_dev, mouse_dev);
-	if (rc != EOK) {
-		usb_mouse_free(&mouse_dev);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data, 
-     uint8_t *buffer, size_t buffer_size)
-{
-	usb_log_debug("usb_mouse_polling_callback()\n");
-	usb_debug_str_buffer(buffer, buffer_size, 0);
-	
-	if (hid_dev == NULL || data == NULL) {
-		usb_log_error("Missing argument to the mouse polling callback."
-		    "\n");
-		return false;
-	}
-	
-	usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
-		
-	return usb_mouse_process_report(hid_dev, mouse_dev, buffer, 
-	                                buffer_size);
-}
-
-/*----------------------------------------------------------------------------*/
-
-void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
-{
-	if (data != NULL) {
-		usb_mouse_free((usb_mouse_t **)&data);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
-{
-	int rc = usb_hid_parse_report_descriptor(hid_dev->report, 
-	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR, 
-	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to parse boot report descriptor: %s\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
-	    hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
-	
-	if (rc != EOK) {
-		usb_log_warning("Failed to set boot protocol to the device: "
-		    "%s\n", str_error(rc));
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,80 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB Mouse driver API.
- */
-
-#ifndef USB_HID_MOUSEDEV_H_
-#define USB_HID_MOUSEDEV_H_
-
-#include <usb/dev/driver.h>
-
-struct usb_hid_dev;
-
-/*----------------------------------------------------------------------------*/
-
-/** Container for USB mouse device. */
-typedef struct {
-	/** IPC phone to console (consumer). */
-	int mouse_phone;
-	int wheel_phone;
-	
-	int32_t *buttons;
-	
-	ddf_dev_ops_t ops;
-} usb_mouse_t;
-
-/*----------------------------------------------------------------------------*/
-
-usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description;
-
-const char *HID_MOUSE_FUN_NAME;
-const char *HID_MOUSE_CLASS_NAME;
-
-/*----------------------------------------------------------------------------*/
-
-int usb_mouse_init(struct usb_hid_dev *hid_dev, void **data);
-
-bool usb_mouse_polling_callback(struct usb_hid_dev *hid_dev, void *data, 
-    uint8_t *buffer, size_t buffer_size);
-
-void usb_mouse_deinit(struct usb_hid_dev *hid_dev, void *data);
-
-int usb_mouse_set_boot_protocol(struct usb_hid_dev *hid_dev);
-
-/*----------------------------------------------------------------------------*/
-
-#endif // USB_HID_MOUSEDEV_H_
-
-/**
- * @}
- */
Index: pace/drv/usbhid/multimedia/keymap.c
===================================================================
--- uspace/drv/usbhid/multimedia/keymap.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,94 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * UUSB multimedia key to keycode mapping.
- */
-
-#include <io/keycode.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <usb/debug.h>
-#include "keymap.h"
-
-/**
- * Mapping between USB HID multimedia usages (from HID Usage Tables) and 
- * corresponding HelenOS key codes.
- *
- * Currently only Usages used by Logitech UltraX keyboard are present. All other
- * should result in 0.
- */
-static int usb_hid_keymap_consumer[0x29c] = {
-	[0xb5] = 0,       /* Scan Next Track */
-	[0xb6] = 0,       /* Scan Previous Track */
-	[0xb7] = 0,       /* Stop */
-	[0xb8] = 0,       /* Eject */
-	[0xcd] = 0/*KC_F2*/,   /* Play/Pause */
-	[0xe2] = 0/*KC_F3*/,   /* Mute */
-	[0xe9] = 0/*KC_F5*/,   /* Volume Increment */
-	[0xea] = 0/*KC_F4*/,   /* Volume Decrement */
-	[0x183] = 0/*KC_F1*/,      /* AL Consumer Control Configuration */
-	[0x18a] = 0,      /* AL Email Reader */
-	[0x192] = 0,      /* AL Calculator */
-	[0x221] = 0,      /* AC Search */
-	[0x223] = 0/*KC_F6*/,      /* AC Home */
-	[0x224] = 0,      /* AC Back */
-	[0x225] = 0,      /* AC Forward */
-	[0x226] = 0,      /* AC Stop */
-	[0x227] = 0,  /* AC Refresh */
-	[0x22a] = 0   /* AC Bookmarks */
-};
-
-/**
- * Translates USB HID Usages from the Consumer Page into HelenOS keycodes.
- *
- * @param usage USB HID Consumer Page Usage number.
- * 
- * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
- */
-unsigned int usb_multimedia_map_usage(int usage)
-{
-	unsigned int key;
-	int *map = usb_hid_keymap_consumer;
-	size_t map_length = sizeof(usb_hid_keymap_consumer) / sizeof(int);
-
-	if ((usage < 0) || ((size_t)usage >= map_length))
-		return -1;
-
-	/*! @todo What if the usage is not in the table? */
-	key = map[usage];
-	
-	return key;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/multimedia/keymap.h
===================================================================
--- uspace/drv/usbhid/multimedia/keymap.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB multimedia key to keycode mapping.
- */
-
-#ifndef USB_HID_MULTIMEDIA_KEYMAP_H_
-#define USB_HID_MULTIMEDIA_KEYMAP_H_
-
-unsigned int usb_multimedia_map_usage(int usage);
-
-#endif /* USB_HID_MULTIMEDIA_KEYMAP_H_ */
-
-/**
- * @}
- */
Index: pace/drv/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/usbhid/multimedia/multimedia.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,342 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/**
- * @file
- * USB Keyboard multimedia keys subdriver.
- */
-
-
-#include "multimedia.h"
-#include "../usbhid.h"
-#include "keymap.h"
-
-#include <usb/hid/hidparser.h>
-#include <usb/debug.h>
-#include <usb/hid/usages/core.h>
-#include <usb/hid/usages/consumer.h>
-
-#include <errno.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <str_error.h>
-
-#include <ipc/kbdev.h>
-#include <io/console.h>
-
-// FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
-
-#define NAME "multimedia-keys"
-
-/*----------------------------------------------------------------------------*/
-/**
- * Logitech UltraX device type.
- */
-typedef struct usb_multimedia_t {
-	/** Previously pressed keys (not translated to key codes). */
-	//int32_t *keys_old;
-	/** Currently pressed keys (not translated to key codes). */
-	//int32_t *keys;
-	/** Count of stored keys (i.e. number of keys in the report). */
-	//size_t key_count;	
-	/** IPC phone to the console device (for sending key events). */
-	int console_phone;
-} usb_multimedia_t;
-
-
-/*----------------------------------------------------------------------------*/
-/** 
- * Default handler for IPC methods not handled by DDF.
- *
- * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
- * assumes the caller is the console and thus it stores IPC phone to it for 
- * later use by the driver to notify about key events.
- *
- * @param fun Device function handling the call.
- * @param icallid Call id.
- * @param icall Call data.
- */
-static void default_connection_handler(ddf_fun_t *fun,
-    ipc_callid_t icallid, ipc_call_t *icall)
-{
-	usb_log_debug(NAME " default_connection_handler()\n");
-	
-	sysarg_t method = IPC_GET_IMETHOD(*icall);
-	
-	usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
-	//usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
-	
-	if (multim_dev == NULL) {
-		async_answer_0(icallid, EINVAL);
-		return;
-	}
-
-	if (method == IPC_M_CONNECT_TO_ME) {
-		int callback = IPC_GET_ARG5(*icall);
-
-		if (multim_dev->console_phone != -1) {
-			async_answer_0(icallid, ELIMIT);
-			return;
-		}
-
-		multim_dev->console_phone = callback;
-		usb_log_debug(NAME " Saved phone to console: %d\n", callback);
-		async_answer_0(icallid, EOK);
-		return;
-	}
-	
-	async_answer_0(icallid, EINVAL);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static ddf_dev_ops_t multimedia_ops = {
-	.default_handler = default_connection_handler
-};
-
-/*----------------------------------------------------------------------------*/
-/**
- * Processes key events.
- *
- * @note This function was copied from AT keyboard driver and modified to suit
- *       USB keyboard.
- *
- * @note Lock keys are not sent to the console, as they are completely handled
- *       in the driver. It may, however, be required later that the driver
- *       sends also these keys to application (otherwise it cannot use those
- *       keys at all).
- * 
- * @param hid_dev 
- * @param lgtch_dev 
- * @param type Type of the event (press / release). Recognized values: 
- *             KEY_PRESS, KEY_RELEASE
- * @param key Key code of the key according to HID Usage Tables.
- */
-static void usb_multimedia_push_ev(usb_hid_dev_t *hid_dev, 
-    usb_multimedia_t *multim_dev, int type, unsigned int key)
-{
-	assert(hid_dev != NULL);
-	assert(multim_dev != NULL);
-	
-	kbd_event_t ev;
-	
-	ev.type = type;
-	ev.key = key;
-	ev.mods = 0;
-	ev.c = 0;
-
-	usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
-	if (multim_dev->console_phone < 0) {
-		usb_log_warning(
-		    "Connection to console not ready, key discarded.\n");
-		return;
-	}
-	
-	async_obsolete_msg_4(multim_dev->console_phone, KBDEV_EVENT, ev.type, ev.key, 
-	    ev.mods, ev.c);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void usb_multimedia_free(usb_multimedia_t **multim_dev)
-{
-	if (multim_dev == NULL || *multim_dev == NULL) {
-		return;
-	}
-	
-	// hangup phone to the console
-	async_obsolete_hangup((*multim_dev)->console_phone);
-
-	free(*multim_dev);
-	*multim_dev = NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_multimedia_create_function(usb_hid_dev_t *hid_dev, 
-    usb_multimedia_t *multim_dev)
-{
-	/* Create the function exposed under /dev/devices. */
-	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
-	    NAME);
-	if (fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	fun->ops = &multimedia_ops;
-	fun->driver_data = multim_dev;   // TODO: maybe change to hid_dev->data
-	
-	int rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	usb_log_debug("%s function created (jandle: %" PRIun ").\n",
-	    NAME, fun->handle);
-	
-	rc = ddf_fun_add_to_class(fun, "keyboard");
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class 'keyboard': %s.\n",
-		    str_error(rc));
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
-{
-	if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
-		return EINVAL; /*! @todo Other return code? */
-	}
-	
-	usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
-	
-	usb_multimedia_t *multim_dev = (usb_multimedia_t *)malloc(
-	    sizeof(usb_multimedia_t));
-	if (multim_dev == NULL) {
-		return ENOMEM;
-	}
-	
-	multim_dev->console_phone = -1;
-	
-	/*! @todo Autorepeat */
-	
-	// save the KBD device structure into the HID device structure
-	*data = multim_dev;
-	
-	usb_log_debug(NAME " HID/multimedia device structure initialized.\n");
-	
-	int rc = usb_multimedia_create_function(hid_dev, multim_dev);
-	if (rc != EOK) {
-		usb_multimedia_free(&multim_dev);
-		return rc;
-	}
-	
-	usb_log_debug(NAME " HID/multimedia structure initialized.\n");
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
-{
-	if (hid_dev == NULL) {
-		return;
-	}
-	
-	if (data != NULL) {
-		usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
-		usb_multimedia_free(&multim_dev);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data, 
-    uint8_t *buffer, size_t buffer_size)
-{
-	// TODO: checks
-	if (hid_dev == NULL || data == NULL || buffer == NULL) {
-		return false;
-	}
-	
-	usb_log_debug(NAME " usb_lgtch_polling_callback(%p, %p, %zu)\n",
-	    hid_dev, buffer, buffer_size);
-	
-	usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
-
-	usb_log_debug(NAME " Calling usb_hid_parse_report() with "
-	    "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0));
-	
-	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
-
-	uint8_t report_id;
-	
-	int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 
-	    &report_id);
-	
-	if (rc != EOK) {
-		usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n", 
-		    str_error(rc));
-		return true;
-	}
-	
-	usb_hid_report_path_set_report_id(path, report_id);
-
-	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
-	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END 
-	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    USB_HID_REPORT_TYPE_INPUT);
-
-	/*! @todo Is this iterating OK if done multiple times? 
-	 *  @todo The parsing is not OK
-	 */
-	while (field != NULL) {
-		if(field->value != 0) {
-			usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
-			    field->value, field->usage);
-			unsigned int key = 
-			    usb_multimedia_map_usage(field->usage);
-			const char *key_str = 
-			    usbhid_multimedia_usage_to_str(field->usage);
-			usb_log_info("Pressed key: %s\n", key_str);
-			usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS, 
-			                       key);
-		}
-		
-		field = usb_hid_report_get_sibling(
-		    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
-		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-		    USB_HID_REPORT_TYPE_INPUT);
-	}	
-
-	usb_hid_report_path_free(path);
-	
-	return true;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/multimedia/multimedia.h
===================================================================
--- uspace/drv/usbhid/multimedia/multimedia.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB Keyboard multimedia keys subdriver.
- */
-
-#ifndef USB_HID_MULTIMEDIA_H_
-#define USB_HID_MULTIMEDIA_H_
-
-#include <usb/dev/driver.h>
-
-struct usb_hid_dev;
-
-/*----------------------------------------------------------------------------*/
-
-int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data);
-
-void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data);
-
-bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data,
-    uint8_t *buffer, size_t buffer_size);
-
-/*----------------------------------------------------------------------------*/
-
-#endif // USB_HID_MULTIMEDIA_H_
-
-/**
- * @}
- */
Index: pace/drv/usbhid/subdrivers.c
===================================================================
--- uspace/drv/usbhid/subdrivers.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,106 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB HID subdriver mappings.
- */
-
-#include "subdrivers.h"
-#include <usb/hid/usages/core.h>
-#include <usb/hid/hidpath.h>
-
-#include "multimedia/multimedia.h"
-#include "mouse/mousedev.h"
-#include "generic/hiddev.h"
-
-static usb_hid_subdriver_usage_t path_kbd[] = {
-	{USB_HIDUT_PAGE_GENERIC_DESKTOP, 
-	 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD}, 
-	{0, 0}
-};
-
-static usb_hid_subdriver_usage_t path_mouse[] = {
-	{USB_HIDUT_PAGE_GENERIC_DESKTOP, USB_HIDUT_USAGE_GENERIC_DESKTOP_MOUSE},
-	{0, 0}
-};
-
-static usb_hid_subdriver_usage_t multim_key_path[] = {
-	{USB_HIDUT_PAGE_CONSUMER, USB_HIDUT_USAGE_CONSUMER_CONSUMER_CONTROL},
-	{0, 0}
-};
-
-const usb_hid_subdriver_mapping_t usb_hid_subdrivers[] = {
-	{
-		path_kbd,
-		0,
-		USB_HID_PATH_COMPARE_BEGIN,
-		-1,
-		-1,
-		{
-			.init = usb_kbd_init,
-			.deinit = usb_kbd_deinit,
-			.poll = usb_kbd_polling_callback,
-			.poll_end = NULL
-		},
-		
-	},
-	{
-		multim_key_path,
-		1,
-		USB_HID_PATH_COMPARE_BEGIN,
-		-1,
-		-1,
-		{
-			.init = usb_multimedia_init,
-			.deinit = usb_multimedia_deinit,
-			.poll = usb_multimedia_polling_callback,
-			.poll_end = NULL
-		}
-	},
-	{
-		path_mouse,
-		0,
-		USB_HID_PATH_COMPARE_BEGIN,
-		-1,
-		-1,
-		{
-			.init = usb_mouse_init,
-			.deinit = usb_mouse_deinit,
-			.poll = usb_mouse_polling_callback,
-			.poll_end = NULL
-		}
-	},
-	{NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL, NULL}}
-};
-
-/**
- * @}
- */
Index: pace/drv/usbhid/subdrivers.h
===================================================================
--- uspace/drv/usbhid/subdrivers.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB HID subdriver mappings.
- */
-
-#ifndef USB_HID_SUBDRIVERS_H_
-#define USB_HID_SUBDRIVERS_H_
-
-#include "usbhid.h"
-#include "kbd/kbddev.h"
-
-/*----------------------------------------------------------------------------*/
-
-typedef struct usb_hid_subdriver_usage {
-	int usage_page;
-	int usage;
-} usb_hid_subdriver_usage_t;
-
-/*----------------------------------------------------------------------------*/
-
-/* TODO: This mapping must contain some other information to get the proper
- *       interface.
- */
-typedef struct usb_hid_subdriver_mapping {
-	const usb_hid_subdriver_usage_t *usage_path;
-	int report_id;
-	int compare;
-	int vendor_id;
-	int product_id;
-	usb_hid_subdriver_t subdriver;
-} usb_hid_subdriver_mapping_t;
-
-/*----------------------------------------------------------------------------*/
-
-extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
-
-/*----------------------------------------------------------------------------*/
-
-#endif /* USB_HID_SUBDRIVERS_H_ */
-
-/**
- * @}
- */
Index: pace/drv/usbhid/usbhid.c
===================================================================
--- uspace/drv/usbhid/usbhid.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,678 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/**
- * @file
- * USB HID driver API.
- */
-
-#include <usb/debug.h>
-#include <usb/classes/classes.h>
-#include <usb/hid/hid.h>
-#include <usb/hid/hidparser.h>
-#include <usb/hid/hidreport.h>
-#include <usb/hid/request.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include "usbhid.h"
-
-#include "kbd/kbddev.h"
-#include "generic/hiddev.h"
-#include "mouse/mousedev.h"
-#include "subdrivers.h"
-
-/*----------------------------------------------------------------------------*/
-
-/* Array of endpoints expected on the device, NULL terminated. */
-usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {
-	&usb_hid_kbd_poll_endpoint_description,
-	&usb_hid_mouse_poll_endpoint_description,
-	&usb_hid_generic_poll_endpoint_description,
-	NULL
-};
-
-static const int USB_HID_MAX_SUBDRIVERS = 10;
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
-{
-	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
-	
-	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
-	    sizeof(usb_hid_subdriver_t));
-	if (hid_dev->subdrivers == NULL) {
-		return ENOMEM;
-	}
-	
-	assert(hid_dev->subdriver_count >= 0);
-	
-	// set the init callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_kbd_init;
-	
-	// set the polling callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
-	    usb_kbd_polling_callback;
-	
-	// set the polling ended callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
-	
-	// set the deinit callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_kbd_deinit;
-	
-	// set subdriver count
-	++hid_dev->subdriver_count;
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
-{
-	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
-	
-	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
-	    sizeof(usb_hid_subdriver_t));
-	if (hid_dev->subdrivers == NULL) {
-		return ENOMEM;
-	}
-	
-	assert(hid_dev->subdriver_count >= 0);
-	
-	// set the init callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_mouse_init;
-	
-	// set the polling callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
-	    usb_mouse_polling_callback;
-	
-	// set the polling ended callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
-	
-	// set the deinit callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_mouse_deinit;
-	
-	// set subdriver count
-	++hid_dev->subdriver_count;
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
-{
-	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
-	
-	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
-	    sizeof(usb_hid_subdriver_t));
-	if (hid_dev->subdrivers == NULL) {
-		return ENOMEM;
-	}
-	
-	assert(hid_dev->subdriver_count >= 0);
-	
-	// set the init callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].init =
-	    usb_generic_hid_init;
-	
-	// set the polling callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
-	    usb_generic_hid_polling_callback;
-	
-	// set the polling ended callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
-	
-	// set the deinit callback
-	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = NULL;
-	
-	// set subdriver count
-	++hid_dev->subdriver_count;
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev, 
-    const usb_hid_subdriver_mapping_t *mapping)
-{
-	assert(hid_dev != NULL);
-	assert(hid_dev->usb_dev != NULL);
-	
-	return (hid_dev->usb_dev->descriptors.device.vendor_id 
-	    == mapping->vendor_id
-	    && hid_dev->usb_dev->descriptors.device.product_id 
-	    == mapping->product_id);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 
-    const usb_hid_subdriver_mapping_t *mapping)
-{
-	assert(hid_dev != NULL);
-	assert(mapping != NULL);
-	
-	usb_hid_report_path_t *usage_path = usb_hid_report_path();
-	if (usage_path == NULL) {
-		usb_log_debug("Failed to create usage path.\n");
-		return false;
-	}
-	int i = 0;
-	while (mapping->usage_path[i].usage != 0 
-	    || mapping->usage_path[i].usage_page != 0) {
-		if (usb_hid_report_path_append_item(usage_path, 
-		    mapping->usage_path[i].usage_page, 
-		    mapping->usage_path[i].usage) != EOK) {
-			usb_log_debug("Failed to append to usage path.\n");
-			usb_hid_report_path_free(usage_path);
-			return false;
-		}
-		++i;
-	}
-	
-	assert(hid_dev->report != NULL);
-	
-	usb_log_debug("Compare flags: %d\n", mapping->compare);
-	
-	bool matches = false;
-	uint8_t report_id = mapping->report_id;
-
-	do {
-		usb_log_debug("Trying report id %u\n", report_id);
-		
-		if (report_id != 0) {
-			usb_hid_report_path_set_report_id(usage_path,
-				report_id);
-		}
-
-		usb_hid_report_field_t *field = usb_hid_report_get_sibling(
-		    hid_dev->report,
-		    NULL, usage_path, mapping->compare, 
-		    USB_HID_REPORT_TYPE_INPUT);
-		
-		usb_log_debug("Field: %p\n", field);
-
-		if (field != NULL) {
-			matches = true;
-			break;
-		}
-		
-		report_id = usb_hid_get_next_report_id(
-		    hid_dev->report, report_id,
-		    USB_HID_REPORT_TYPE_INPUT);
-	} while (!matches && report_id != 0);
-	
-	usb_hid_report_path_free(usage_path);
-	
-	return matches;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 
-    const usb_hid_subdriver_t **subdrivers, int count)
-{
-	int i;
-	
-	if (count <= 0) {
-		hid_dev->subdriver_count = 0;
-		hid_dev->subdrivers = NULL;
-		return EOK;
-	}
-	
-	// add one generic HID subdriver per device
-	
-	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) * 
-	    sizeof(usb_hid_subdriver_t));
-	if (hid_dev->subdrivers == NULL) {
-		return ENOMEM;
-	}
-	
-	for (i = 0; i < count; ++i) {
-		hid_dev->subdrivers[i].init = subdrivers[i]->init;
-		hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
-		hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
-		hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
-	}
-	
-	hid_dev->subdrivers[count].init = usb_generic_hid_init;
-	hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback;
-	hid_dev->subdrivers[count].deinit = NULL;
-	hid_dev->subdrivers[count].poll_end = NULL;
-	
-	hid_dev->subdriver_count = count + 1;
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
-{
-	assert(hid_dev != NULL);
-	
-	const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
-	
-	int i = 0, count = 0;
-	const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
-
-	bool ids_matched;
-	bool matched;
-	
-	while (count < USB_HID_MAX_SUBDRIVERS &&
-	    (mapping->usage_path != NULL
-	    || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
-		// check the vendor & product ID
-		if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
-			usb_log_warning("Missing Product ID for Vendor ID %d\n",
-			    mapping->vendor_id);
-			return EINVAL;
-		}
-		if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
-			usb_log_warning("Missing Vendor ID for Product ID %d\n",
-			    mapping->product_id);
-			return EINVAL;
-		}
-		
-		ids_matched = false;
-		matched = false;
-		
-		if (mapping->vendor_id >= 0) {
-			assert(mapping->product_id >= 0);
-			usb_log_debug("Comparing device against vendor ID %u"
-			    " and product ID %u.\n", mapping->vendor_id,
-			    mapping->product_id);
-			if (usb_hid_ids_match(hid_dev, mapping)) {
-				usb_log_debug("IDs matched.\n");
-				ids_matched = true;
-			}
-		}
-		
-		if (mapping->usage_path != NULL) {
-			usb_log_debug("Comparing device against usage path.\n");
-			if (usb_hid_path_matches(hid_dev, mapping)) {
-				// does not matter if IDs were matched
-				matched = true;
-			}
-		} else {
-			// matched only if IDs were matched and there is no path
-			matched = ids_matched;
-		}
-		
-		if (matched) {
-			usb_log_debug("Subdriver matched.\n");
-			subdrivers[count++] = &mapping->subdriver;
-		}
-		
-		mapping = &usb_hid_subdrivers[++i];
-	}
-	
-	// we have all subdrivers determined, save them into the hid device
-	return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
-{
-	assert(hid_dev != NULL && dev != NULL);
-	
-	int rc = EOK;
-	
-	if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
-		usb_log_debug("Found keyboard endpoint.\n");
-		// save the pipe index
-		hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
-	} else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
-		usb_log_debug("Found mouse endpoint.\n");
-		// save the pipe index
-		hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
-	} else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
-		usb_log_debug("Found generic HID endpoint.\n");
-		// save the pipe index
-		hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
-	} else {
-		usb_log_error("None of supported endpoints found - probably"
-		    " not a supported device.\n");
-		rc = ENOTSUP;
-	}
-	
-	return rc;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
-{
-	assert(hid_dev != NULL && hid_dev->report != NULL);
-	
-	uint8_t report_id = 0;
-	size_t size;
-	
-	size_t max_size = 0;
-	
-	do {
-		usb_log_debug("Getting size of the report.\n");
-		size = usb_hid_report_byte_size(hid_dev->report, report_id, 
-		    USB_HID_REPORT_TYPE_INPUT);
-		usb_log_debug("Report ID: %u, size: %zu\n", report_id, size);
-		max_size = (size > max_size) ? size : max_size;
-		usb_log_debug("Getting next report ID\n");
-		report_id = usb_hid_get_next_report_id(hid_dev->report, 
-		    report_id, USB_HID_REPORT_TYPE_INPUT);
-	} while (report_id != 0);
-	
-	usb_log_debug("Max size of input report: %zu\n", max_size);
-	
-	hid_dev->max_input_report_size = max_size;
-	assert(hid_dev->input_report == NULL);
-	
-	hid_dev->input_report = malloc(max_size);
-	if (hid_dev->input_report == NULL) {
-		return ENOMEM;
-	}
-	memset(hid_dev->input_report, 0, max_size);
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-usb_hid_dev_t *usb_hid_new(void)
-{
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)calloc(1,
-	    sizeof(usb_hid_dev_t));
-	
-	if (hid_dev == NULL) {
-		usb_log_fatal("No memory!\n");
-		return NULL;
-	}
-	
-	hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
-	    usb_hid_report_t)));
-	if (hid_dev->report == NULL) {
-		usb_log_fatal("No memory!\n");
-		free(hid_dev);
-		return NULL;
-	}
-	
-	hid_dev->poll_pipe_index = -1;
-	
-	return hid_dev;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
-{
-	int rc, i;
-	
-	usb_log_debug("Initializing HID structure...\n");
-	
-	if (hid_dev == NULL) {
-		usb_log_error("Failed to init HID structure: no structure given"
-		    ".\n");
-		return EINVAL;
-	}
-	
-	if (dev == NULL) {
-		usb_log_error("Failed to init HID structure: no USB device"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	/* The USB device should already be initialized, save it in structure */
-	hid_dev->usb_dev = dev;
-	
-	rc = usb_hid_check_pipes(hid_dev, dev);
-	if (rc != EOK) {
-		return rc;
-	}
-		
-	/* Get the report descriptor and parse it. */
-	rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 
-	    hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
-	
-	bool fallback = false;
-	
-	if (rc == EOK) {
-		// try to find subdrivers that may want to handle this device
-		rc = usb_hid_find_subdrivers(hid_dev);
-		if (rc != EOK || hid_dev->subdriver_count == 0) {
-			// try to fall back to the boot protocol if available
-			usb_log_info("No subdrivers found to handle this"
-			    " device.\n");
-			fallback = true;
-			assert(hid_dev->subdrivers == NULL);
-			assert(hid_dev->subdriver_count == 0);
-		}
-	} else {
-		usb_log_error("Failed to parse Report descriptor.\n");
-		// try to fall back to the boot protocol if available
-		fallback = true;
-	}
-	
-	if (fallback) {
-		// fall back to boot protocol
-		switch (hid_dev->poll_pipe_index) {
-		case USB_HID_KBD_POLL_EP_NO:
-			usb_log_info("Falling back to kbd boot protocol.\n");
-			rc = usb_kbd_set_boot_protocol(hid_dev);
-			if (rc == EOK) {
-				rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
-			}
-			break;
-		case USB_HID_MOUSE_POLL_EP_NO:
-			usb_log_info("Falling back to mouse boot protocol.\n");
-			rc = usb_mouse_set_boot_protocol(hid_dev);
-			if (rc == EOK) {
-				rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
-			}
-			break;
-		default:
-			assert(hid_dev->poll_pipe_index 
-			    == USB_HID_GENERIC_POLL_EP_NO);
-			
-			usb_log_info("Falling back to generic HID driver.\n");
-			rc = usb_hid_set_generic_hid_subdriver(hid_dev);
-		}
-	}
-	
-	if (rc != EOK) {
-		usb_log_error("No subdriver for handling this device could be"
-		    " initialized: %s.\n", str_error(rc));
-		usb_log_debug("Subdriver count: %d\n", 
-		    hid_dev->subdriver_count);
-		
-	} else {
-		bool ok = false;
-		
-		usb_log_debug("Subdriver count: %d\n", 
-		    hid_dev->subdriver_count);
-		
-		for (i = 0; i < hid_dev->subdriver_count; ++i) {
-			if (hid_dev->subdrivers[i].init != NULL) {
-				usb_log_debug("Initializing subdriver %d.\n",i);
-				rc = hid_dev->subdrivers[i].init(hid_dev,
-				    &hid_dev->subdrivers[i].data);
-				if (rc != EOK) {
-					usb_log_warning("Failed to initialize"
-					    " HID subdriver structure.\n");
-				} else {
-					// at least one subdriver initialized
-					ok = true;
-				}
-			} else {
-				ok = true;
-			}
-		}
-		
-		rc = (ok) ? EOK : -1;	// what error to report
-	}
-	
-	
-	if (rc == EOK) {
-		// save max input report size and allocate space for the report
-		rc = usb_hid_init_report(hid_dev);
-		if (rc != EOK) {
-			usb_log_error("Failed to initialize input report buffer"
-			    ".\n");
-		}
-	}
-	
-	
-	return rc;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
-    size_t buffer_size, void *arg)
-{
-	int i;
-	
-	if (dev == NULL || arg == NULL || buffer == NULL) {
-		usb_log_error("Missing arguments to polling callback.\n");
-		return false;
-	}
-	
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
-	
-	assert(hid_dev->input_report != NULL);
-	usb_log_debug("Max input report size: %zu, buffer size: %zu\n",
-	    hid_dev->max_input_report_size, buffer_size);
-
-	if (hid_dev->max_input_report_size >= buffer_size) {
-		/*! @todo This should probably be atomic. */
-		memcpy(hid_dev->input_report, buffer, buffer_size);
-		hid_dev->input_report_size = buffer_size;
-		usb_hid_new_report(hid_dev);
-	}
-	
-	bool cont = false;
-	
-	// continue if at least one of the subdrivers want to continue
-	for (i = 0; i < hid_dev->subdriver_count; ++i) {
-		if (hid_dev->subdrivers[i].poll != NULL
-		    && hid_dev->subdrivers[i].poll(hid_dev, 
-		        hid_dev->subdrivers[i].data, buffer, buffer_size)) {
-			cont = true;
-		}
-	}
-	
-	return cont;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, 
-     void *arg)
-{
-	int i; 
-	
-	if (dev == NULL || arg == NULL) {
-		return;
-	}
-	
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
-	
-	for (i = 0; i < hid_dev->subdriver_count; ++i) {
-		if (hid_dev->subdrivers[i].poll_end != NULL) {
-			hid_dev->subdrivers[i].poll_end(hid_dev,
-			    hid_dev->subdrivers[i].data, reason);
-		}
-	}
-	
-	usb_hid_free(&hid_dev);
-}
-
-/*----------------------------------------------------------------------------*/
-
-void usb_hid_new_report(usb_hid_dev_t *hid_dev)
-{
-	++hid_dev->report_nr;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int usb_hid_report_number(usb_hid_dev_t *hid_dev)
-{
-	return hid_dev->report_nr;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void usb_hid_free(usb_hid_dev_t **hid_dev)
-{
-	int i;
-	
-	if (hid_dev == NULL || *hid_dev == NULL) {
-		return;
-	}
-	
-	usb_log_debug("Subdrivers: %p, subdriver count: %d\n", 
-	    (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count);
-	
-	assert((*hid_dev)->subdrivers != NULL 
-	    || (*hid_dev)->subdriver_count == 0);
-	
-	for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
-		if ((*hid_dev)->subdrivers[i].deinit != NULL) {
-			(*hid_dev)->subdrivers[i].deinit(*hid_dev,
-			    (*hid_dev)->subdrivers[i].data);
-		}
-	}
-	
-	// free the subdrivers info
-	if ((*hid_dev)->subdrivers != NULL) {
-		free((*hid_dev)->subdrivers);
-	}
-
-	// destroy the parser
-	if ((*hid_dev)->report != NULL) {
-		usb_hid_free_report((*hid_dev)->report);
-	}
-
-	if ((*hid_dev)->report_desc != NULL) {
-		free((*hid_dev)->report_desc);
-	}
-
-	free(*hid_dev);
-	*hid_dev = NULL;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/usbhid.h
===================================================================
--- uspace/drv/usbhid/usbhid.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,137 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup drvusbhid
- * @{
- */
-/** @file
- * USB HID driver API.
- */
-
-#ifndef USB_HID_USBHID_H_
-#define USB_HID_USBHID_H_
-
-#include <stdint.h>
-
-#include <usb/hid/hidparser.h>
-#include <ddf/driver.h>
-#include <usb/dev/pipes.h>
-#include <usb/dev/driver.h>
-#include <usb/hid/hid.h>
-#include <bool.h>
-
-struct usb_hid_dev;
-
-typedef int (*usb_hid_driver_init_t)(struct usb_hid_dev *, void **data);
-typedef void (*usb_hid_driver_deinit_t)(struct usb_hid_dev *, void *data);
-typedef bool (*usb_hid_driver_poll)(struct usb_hid_dev *, void *data, uint8_t *,
-                                    size_t);
-typedef int (*usb_hid_driver_poll_ended)(struct usb_hid_dev *, void *data, 
-                                         bool reason);
-
-typedef struct usb_hid_subdriver {	
-	/** Function to be called when initializing HID device. */
-	usb_hid_driver_init_t init;
-	/** Function to be called when destroying the HID device structure. */
-	usb_hid_driver_deinit_t deinit;
-	/** Function to be called when data arrives from the device. */
-	usb_hid_driver_poll poll;
-	/** Function to be called when polling ends. */
-	usb_hid_driver_poll_ended poll_end;
-	/** Arbitrary data needed by the subdriver. */
-	void *data;
-} usb_hid_subdriver_t;
-
-/*----------------------------------------------------------------------------*/
-/**
- * Structure for holding general HID device data.
- */
-typedef struct usb_hid_dev {
-	/** Structure holding generic USB device information. */
-	usb_device_t *usb_dev;
-	
-	/** Index of the polling pipe in usb_hid_endpoints array. */
-	int poll_pipe_index;
-	
-	/** Subdrivers. */
-	usb_hid_subdriver_t *subdrivers;
-	
-	/** Number of subdrivers. */
-	int subdriver_count;
-	
-	/** Report descriptor. */
-	uint8_t *report_desc;
-
-	/** Report descriptor size. */
-	size_t report_desc_size;
-	
-	/** HID Report parser. */
-	usb_hid_report_t *report;
-	
-	uint8_t *input_report;
-	
-	size_t input_report_size;
-	size_t max_input_report_size;
-	
-	int report_nr;
-} usb_hid_dev_t;
-
-/*----------------------------------------------------------------------------*/
-
-enum {
-	USB_HID_KBD_POLL_EP_NO = 0,
-	USB_HID_MOUSE_POLL_EP_NO = 1,
-	USB_HID_GENERIC_POLL_EP_NO = 2,
-	USB_HID_POLL_EP_COUNT = 3
-};
-
-usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1];
-
-/*----------------------------------------------------------------------------*/
-
-usb_hid_dev_t *usb_hid_new(void);
-
-int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
-
-bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
-    size_t buffer_size, void *arg);
-
-void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, 
-     void *arg);
-
-void usb_hid_new_report(usb_hid_dev_t *hid_dev);
-
-int usb_hid_report_number(usb_hid_dev_t *hid_dev);
-
-void usb_hid_free(usb_hid_dev_t **hid_dev);
-
-#endif /* USB_HID_USBHID_H_ */
-
-/**
- * @}
- */
Index: pace/drv/usbhid/usbhid.ma
===================================================================
--- uspace/drv/usbhid/usbhid.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,3 +1,0 @@
-100 usb&interface&class=HID&subclass=0x01&protocol=0x01
-1000 usb&interface&class=HID&subclass=0x01&protocol=0x02
-100 usb&interface&class=HID
Index: pace/drv/usbhub/Makefile
===================================================================
--- uspace/drv/usbhub/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,48 +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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = usbhub
-
-SOURCES = \
-	main.c \
-	utils.c \
-	usbhub.c \
-	ports.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/usbhub/main.c
===================================================================
--- uspace/drv/usbhub/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,96 +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 drvusbhub
- * @{
- */
-
-#include <ddf/driver.h>
-#include <errno.h>
-#include <async.h>
-#include <stdio.h>
-
-#include <usb/dev/driver.h>
-#include <usb/classes/classes.h>
-
-#include "usbhub.h"
-#include "usbhub_private.h"
-
-/** Hub status-change endpoint description.
- *
- * For more information see section 11.15.1 of USB 1.1 specification.
- */
-static usb_endpoint_description_t hub_status_change_endpoint_description = {
-	.transfer_type = USB_TRANSFER_INTERRUPT,
-	.direction = USB_DIRECTION_IN,
-	.interface_class = USB_CLASS_HUB,
-	.interface_subclass = 0,
-	.interface_protocol = 0,
-	.flags = 0
-};
-
-/**
- * usb hub driver operations
- *
- * The most important one is add_device, which is set to usb_hub_add_device.
- */
-static usb_driver_ops_t usb_hub_driver_ops = {
-	.add_device = usb_hub_add_device
-};
-
-/**
- * hub endpoints, excluding control endpoint
- */
-static usb_endpoint_description_t *usb_hub_endpoints[] = {
-	&hub_status_change_endpoint_description,
-	NULL
-};
-
-/**
- * static usb hub driver information
- */
-static usb_driver_t usb_hub_driver = {
-	.name = NAME,
-	.ops = &usb_hub_driver_ops,
-	.endpoints = usb_hub_endpoints
-};
-
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS USB hub driver.\n");
-
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-
-	return usb_driver_main(&usb_hub_driver);
-}
-
-/**
- * @}
- */
-
Index: pace/drv/usbhub/port_status.h
===================================================================
--- uspace/drv/usbhub/port_status.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,360 +1,0 @@
-/*
- * Copyright (c) 2010 Matus Dekanek
- * 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 drvusbhub
- * @{
- */
-
-#ifndef HUB_PORT_STATUS_H
-#define	HUB_PORT_STATUS_H
-
-#include <bool.h>
-#include <sys/types.h>
-#include <usb/dev/request.h>
-#include "usbhub_private.h"
-
-/**
- * structure holding port status and changes flags.
- * should not be accessed directly, use supplied getter/setter methods.
- *
- * For more information refer to table 11-15 in
- * "Universal Serial Bus Specification Revision 1.1"
- *
- */
-typedef uint32_t usb_port_status_t;
-
-/**
- * structure holding hub status and changes flags.
- * should not be accessed directly, use supplied getter/setter methods.
- *
- * For more information refer to table 11.16.2.5 in
- * "Universal Serial Bus Specification Revision 1.1"
- *
- */
-typedef uint32_t usb_hub_status_t;
-
-/**
- * set values in request to be it a port status request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_port_status_request(
-    usb_device_request_setup_packet_t *request, uint16_t port) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
-	request->request = USB_HUB_REQUEST_GET_STATUS;
-	request->value = 0;
-	request->length = 4;
-}
-
-/**
- * set values in request to be it a port status request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_hub_status_request(
-    usb_device_request_setup_packet_t *request) {
-	request->index = 0;
-	request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;
-	request->request = USB_HUB_REQUEST_GET_STATUS;
-	request->value = 0;
-	request->length = 4;
-}
-
-/**
- * create request for usb hub port status
- * @param port
- * @return
- */
-static inline usb_device_request_setup_packet_t *
-usb_hub_create_port_status_request(uint16_t port) {
-	usb_device_request_setup_packet_t *result =
-	    malloc(sizeof (usb_device_request_setup_packet_t));
-	usb_hub_set_port_status_request(result, port);
-	return result;
-}
-
-/**
- * set the device request to be a port feature enable request
- * @param request
- * @param port
- * @param feature_selector
- */
-static inline void usb_hub_set_enable_port_feature_request(
-    usb_device_request_setup_packet_t *request, uint16_t port,
-    uint16_t feature_selector) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = feature_selector;
-	request->length = 0;
-}
-
-/**
- * set the device request to be a port feature clear request
- * @param request
- * @param port
- * @param feature_selector
- */
-static inline void usb_hub_set_disable_port_feature_request(
-    usb_device_request_setup_packet_t *request, uint16_t port,
-    uint16_t feature_selector
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
-	request->value = feature_selector;
-	request->length = 0;
-}
-
-/**
- * set the device request to be a port enable request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_enable_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = USB_HUB_FEATURE_C_PORT_ENABLE;
-	request->length = 0;
-}
-
-/**
- * enable specified port
- * @param port
- * @return
- */
-static inline usb_device_request_setup_packet_t *
-usb_hub_create_enable_port_request(uint16_t port) {
-	usb_device_request_setup_packet_t *result =
-	    malloc(sizeof (usb_device_request_setup_packet_t));
-	usb_hub_set_enable_port_request(result, port);
-	return result;
-}
-
-/**
- * set the device request to be a port disable request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_disable_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = USB_HUB_FEATURE_C_PORT_SUSPEND;
-	request->length = 0;
-}
-
-/**
- * disable specified port
- * @param port
- * @return
- */
-static inline usb_device_request_setup_packet_t *
-usb_hub_create_disable_port_request(uint16_t port) {
-	usb_device_request_setup_packet_t *result =
-	    malloc(sizeof (usb_device_request_setup_packet_t));
-	usb_hub_set_disable_port_request(result, port);
-	return result;
-}
-
-/**
- * set the device request to be a port disable request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_reset_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = USB_HUB_FEATURE_PORT_RESET;
-	request->length = 0;
-}
-
-/**
- * disable specified port
- * @param port
- * @return
- */
-static inline usb_device_request_setup_packet_t *
-usb_hub_create_reset_port_request(uint16_t port) {
-	usb_device_request_setup_packet_t *result =
-	    malloc(sizeof (usb_device_request_setup_packet_t));
-	usb_hub_set_reset_port_request(result, port);
-	return result;
-}
-
-/**
- * set the device request to be a port disable request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_power_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = USB_HUB_FEATURE_PORT_POWER;
-	request->length = 0;
-}
-
-/**
- * set the device request to be a port disable request
- * @param request
- * @param port
- */
-static inline void usb_hub_unset_power_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
-	request->value = USB_HUB_FEATURE_PORT_POWER;
-	request->length = 0;
-}
-
-/**
- * get i`th bit of port status
- * 
- * @param status
- * @param idx
- * @return
- */
-static inline bool usb_port_is_status(usb_port_status_t status, int idx) {
-	return (status & (1 << idx)) != 0;
-}
-
-/**
- * set i`th bit of port status
- * 
- * @param status
- * @param idx
- * @param value
- */
-static inline void usb_port_status_set_bit(
-    usb_port_status_t * status, int idx, bool value) {
-	(*status) = value ?
-	    ((*status) | (1 << (idx))) :
-	    ((*status)&(~(1 << (idx))));
-}
-
-/**
- * get i`th bit of hub status
- * 
- * @param status
- * @param idx
- * @return
- */
-static inline bool usb_hub_is_status(usb_hub_status_t status, int idx) {
-	return (status & (1 << idx)) != 0;
-}
-
-/**
- * set i`th bit of hub status
- * 
- * @param status
- * @param idx
- * @param value
- */
-static inline void usb_hub_status_set_bit(
-    usb_hub_status_t *status, int idx, bool value) {
-	(*status) = value ?
-	    ((*status) | (1 << (idx))) :
-	    ((*status)&(~(1 << (idx))));
-}
-
-/**
- * low speed device on the port indicator
- * 
- * @param status
- * @return true if low speed device is attached
- */
-static inline bool usb_port_low_speed(usb_port_status_t status) {
-	return usb_port_is_status(status, 9);
-}
-
-/**
- * set low speed device connected bit in port status
- * 
- * @param status
- * @param low_speed value of the bit
- */
-static inline void usb_port_set_low_speed(usb_port_status_t *status, bool low_speed) {
-	usb_port_status_set_bit(status, 9, low_speed);
-}
-
-//high speed device attached
-
-/**
- * high speed device on the port indicator
- *
- * @param status
- * @return true if high speed device is on port
- */
-static inline bool usb_port_high_speed(usb_port_status_t status) {
-	return usb_port_is_status(status, 10);
-}
-
-/**
- * set high speed device bit in port status
- *
- * @param status
- * @param high_speed value of the bit
- */
-static inline void usb_port_set_high_speed(usb_port_status_t *status, bool high_speed) {
-	usb_port_status_set_bit(status, 10, high_speed);
-}
-
-/**
- * speed getter for port status
- *
- * @param status
- * @return speed of usb device (for more see usb specification)
- */
-static inline usb_speed_t usb_port_speed(usb_port_status_t status) {
-	if (usb_port_low_speed(status))
-		return USB_SPEED_LOW;
-	if (usb_port_high_speed(status))
-		return USB_SPEED_HIGH;
-	return USB_SPEED_FULL;
-}
-
-
-
-#endif	/* HUB_PORT_STATUS_H */
-
-/**
- * @}
- */
Index: pace/drv/usbhub/ports.c
===================================================================
--- uspace/drv/usbhub/ports.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,465 +1,0 @@
-/*
- * 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 drvusbhub
- * @{
- */
-/** @file
- * Hub ports functions.
- */
-
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <inttypes.h>
-#include <fibril_synch.h>
-
-#include <usb/debug.h>
-
-#include "ports.h"
-#include "usbhub.h"
-#include "usbhub_private.h"
-#include "port_status.h"
-
-/** Information for fibril for device discovery. */
-struct add_device_phase1 {
-	usb_hub_info_t *hub;
-	size_t port;
-	usb_speed_t speed;
-};
-
-/**
- * count of port status changes that are not explicitly handled by
- * any function here and must be cleared by hand
- */
-static const unsigned int non_handled_changes_count = 2;
-
-/**
- * port status changes that are not explicitly handled by
- * any function here and must be cleared by hand
- */
-static const int non_handled_changes[] = {
-	USB_HUB_FEATURE_C_PORT_ENABLE,
-	USB_HUB_FEATURE_C_PORT_SUSPEND
-};
-
-static void usb_hub_removed_device(
-    usb_hub_info_t *hub, uint16_t port);
-
-static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
-    uint16_t port, uint32_t status);
-
-static void usb_hub_port_over_current(usb_hub_info_t *hub,
-    uint16_t port, uint32_t status);
-
-static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
-    usb_port_status_t *status);
-
-static int enable_port_callback(int port_no, void *arg);
-
-static int add_device_phase1_worker_fibril(void *arg);
-
-static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
-    usb_speed_t speed);
-
-/**
- * Process interrupts on given hub port
- *
- * Accepts connection, over current and port reset change.
- * @param hub hub representation
- * @param port port number, starting from 1
- */
-void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
-    uint16_t port) {
-	usb_log_debug("Interrupt at port %zu\n", (size_t) port);
-	//determine type of change
-	//usb_pipe_t *pipe = hub->control_pipe;
-
-	int opResult;
-
-	usb_port_status_t status;
-	opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);
-	if (opResult != EOK) {
-		usb_log_error("Failed to get port %zu status: %s.\n",
-		    (size_t) port, str_error(opResult));
-		return;
-	}
-	//connection change
-	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {
-		bool device_connected = usb_port_is_status(status,
-		    USB_HUB_FEATURE_PORT_CONNECTION);
-		usb_log_debug("Connection change on port %zu: %s.\n",
-		    (size_t) port,
-		    device_connected ? "device attached" : "device removed");
-
-		if (device_connected) {
-			opResult = create_add_device_fibril(hub, port,
-			    usb_port_speed(status));
-			if (opResult != EOK) {
-				usb_log_error(
-				    "Cannot handle change on port %zu: %s.\n",
-				    (size_t) port, str_error(opResult));
-			}
-		} else {
-			usb_hub_removed_device(hub, port);
-		}
-	}
-	//over current
-	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {
-		//check if it was not auto-resolved
-		usb_log_debug("Overcurrent change on port\n");
-		usb_hub_port_over_current(hub, port, status);
-	}
-	//port reset
-	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {
-		usb_hub_port_reset_completed(hub, port, status);
-	}
-	usb_log_debug("Status x%x : %d\n ", status, status);
-
-	usb_port_status_set_bit(
-	    &status, USB_HUB_FEATURE_C_PORT_CONNECTION, false);
-	usb_port_status_set_bit(
-	    &status, USB_HUB_FEATURE_C_PORT_RESET, false);
-	usb_port_status_set_bit(
-	    &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT, false);
-
-	//clearing not yet handled changes	
-	unsigned int feature_idx;
-	for (feature_idx = 0;
-	    feature_idx < non_handled_changes_count;
-	    ++feature_idx) {
-		unsigned int bit_idx = non_handled_changes[feature_idx];
-		if (status & (1 << bit_idx)) {
-			usb_log_info(
-			    "There was not yet handled change on port %d: %d"
-			    ";clearing it\n",
-			    port, bit_idx);
-			int opResult = usb_hub_clear_port_feature(
-			    hub->control_pipe,
-			    port, bit_idx);
-			if (opResult != EOK) {
-				usb_log_warning(
-				    "Could not clear port flag %d: %s\n",
-				    bit_idx, str_error(opResult)
-				    );
-			}
-			usb_port_status_set_bit(
-			    &status, bit_idx, false);
-		}
-	}
-	if (status >> 16) {
-		usb_log_info("There is still some unhandled change %X\n",
-		    status);
-	}
-}
-
-/**
- * routine called when a device on port has been removed
- *
- * If the device on port had default address, it releases default address.
- * Otherwise does not do anything, because DDF does not allow to remove device
- * from it`s device tree.
- * @param hub hub representation
- * @param port port number, starting from 1
- */
-static void usb_hub_removed_device(
-    usb_hub_info_t *hub, uint16_t port) {
-
-	int opResult = usb_hub_clear_port_feature(hub->control_pipe,
-	    port, USB_HUB_FEATURE_C_PORT_CONNECTION);
-	if (opResult != EOK) {
-		usb_log_warning("Could not clear port-change-connection flag\n");
-	}
-	/** \TODO remove device from device manager - not yet implemented in
-	 * devide manager
-	 */
-
-	//close address
-
-	usb_hub_port_t *the_port = hub->ports + port;
-
-	fibril_mutex_lock(&hub->port_mutex);
-
-	if (the_port->attached_device.address >= 0) {
-		usb_log_warning("Device unplug on `%s' (port %zu): " \
-		    "not implemented.\n", hub->usb_device->ddf_dev->name,
-		    (size_t) port);
-		the_port->attached_device.address = -1;
-		the_port->attached_device.handle = 0;
-	} else {
-		usb_log_warning("Device removed before being registered.\n");
-
-		/*
-		 * Device was removed before port reset completed.
-		 * We will announce a failed port reset to unblock the
-		 * port reset callback from new device wrapper.
-		 */
-		fibril_mutex_lock(&the_port->reset_mutex);
-		the_port->reset_completed = true;
-		the_port->reset_okay = false;
-		fibril_condvar_broadcast(&the_port->reset_cv);
-		fibril_mutex_unlock(&the_port->reset_mutex);
-	}
-
-	fibril_mutex_unlock(&hub->port_mutex);
-}
-
-/**
- * Process port reset change
- *
- * After this change port should be enabled, unless some problem occured.
- * This functions triggers second phase of enabling new device.
- * @param hub
- * @param port
- * @param status
- */
-static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
-    uint16_t port, uint32_t status) {
-	usb_log_debug("Port %zu reset complete.\n", (size_t) port);
-	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {
-		/* Finalize device adding. */
-		usb_hub_port_t *the_port = hub->ports + port;
-		fibril_mutex_lock(&the_port->reset_mutex);
-		the_port->reset_completed = true;
-		the_port->reset_okay = true;
-		fibril_condvar_broadcast(&the_port->reset_cv);
-		fibril_mutex_unlock(&the_port->reset_mutex);
-	} else {
-		usb_log_warning(
-		    "Port %zu reset complete but port not enabled.\n",
-		    (size_t) port);
-	}
-	/* Clear the port reset change. */
-	int rc = usb_hub_clear_port_feature(hub->control_pipe,
-	    port, USB_HUB_FEATURE_C_PORT_RESET);
-	if (rc != EOK) {
-		usb_log_error("Failed to clear port %d reset feature: %s.\n",
-		    port, str_error(rc));
-	}
-}
-
-/**
- * Process over current condition on port.
- *
- * Turn off the power on the port.
- *
- * @param hub hub representation
- * @param port port number, starting from 1
- */
-static void usb_hub_port_over_current(usb_hub_info_t *hub,
-    uint16_t port, uint32_t status) {
-	int opResult;
-	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)) {
-		opResult = usb_hub_clear_port_feature(hub->control_pipe,
-		    port, USB_HUB_FEATURE_PORT_POWER);
-		if (opResult != EOK) {
-			usb_log_error("Cannot power off port %d; %s\n",
-			    port, str_error(opResult));
-		}
-	} else {
-		opResult = usb_hub_set_port_feature(hub->control_pipe,
-		    port, USB_HUB_FEATURE_PORT_POWER);
-		if (opResult != EOK) {
-			usb_log_error("Cannot power on port %d; %s\n",
-			    port, str_error(opResult));
-		}
-	}
-}
-
-/** Retrieve port status.
- *
- * @param[in] ctrl_pipe Control pipe to use.
- * @param[in] port Port number (starting at 1).
- * @param[out] status Where to store the port status.
- * @return Error code.
- */
-static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
-    usb_port_status_t *status) {
-	size_t recv_size;
-	usb_device_request_setup_packet_t request;
-	usb_port_status_t status_tmp;
-
-	usb_hub_set_port_status_request(&request, port);
-	int rc = usb_pipe_control_read(ctrl_pipe,
-	    &request, sizeof (usb_device_request_setup_packet_t),
-	    &status_tmp, sizeof (status_tmp), &recv_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (recv_size != sizeof (status_tmp)) {
-		return ELIMIT;
-	}
-
-	if (status != NULL) {
-		*status = status_tmp;
-	}
-
-	return EOK;
-}
-
-/** Callback for enabling a specific port.
- *
- * We wait on a CV until port is reseted.
- * That is announced via change on interrupt pipe.
- *
- * @param port_no Port number (starting at 1).
- * @param arg Custom argument, points to @c usb_hub_info_t.
- * @return Error code.
- */
-static int enable_port_callback(int port_no, void *arg) {
-	usb_hub_info_t *hub = arg;
-	int rc;
-	usb_device_request_setup_packet_t request;
-	usb_hub_port_t *my_port = hub->ports + port_no;
-
-	usb_hub_set_reset_port_request(&request, port_no);
-	rc = usb_pipe_control_write(hub->control_pipe,
-	    &request, sizeof (request), NULL, 0);
-	if (rc != EOK) {
-		usb_log_warning("Port reset failed: %s.\n", str_error(rc));
-		return rc;
-	}
-
-	/*
-	 * Wait until reset completes.
-	 */
-	fibril_mutex_lock(&my_port->reset_mutex);
-	while (!my_port->reset_completed) {
-		fibril_condvar_wait(&my_port->reset_cv, &my_port->reset_mutex);
-	}
-	fibril_mutex_unlock(&my_port->reset_mutex);
-
-	if (my_port->reset_okay) {
-		return EOK;
-	} else {
-		return ESTALL;
-	}
-}
-
-/** Fibril for adding a new device.
- *
- * Separate fibril is needed because the port reset completion is announced
- * via interrupt pipe and thus we cannot block here.
- *
- * @param arg Pointer to struct add_device_phase1.
- * @return 0 Always.
- */
-static int add_device_phase1_worker_fibril(void *arg) {
-	struct add_device_phase1 *data
-	    = (struct add_device_phase1 *) arg;
-
-	usb_address_t new_address;
-	devman_handle_t child_handle;
-
-	int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
-	    &data->hub->connection, data->speed,
-	    enable_port_callback, (int) data->port, data->hub,
-	    &new_address, &child_handle,
-	    NULL, NULL, NULL);
-
-	if (rc != EOK) {
-		usb_log_error("Failed registering device on port %zu: %s.\n",
-		    data->port, str_error(rc));
-		goto leave;
-	}
-
-	fibril_mutex_lock(&data->hub->port_mutex);
-	data->hub->ports[data->port].attached_device.handle = child_handle;
-	data->hub->ports[data->port].attached_device.address = new_address;
-	fibril_mutex_unlock(&data->hub->port_mutex);
-
-	usb_log_info("Detected new device on `%s' (port %zu), "
-	    "address %d (handle %" PRIun ").\n",
-	    data->hub->usb_device->ddf_dev->name, data->port,
-	    new_address, child_handle);
-
-leave:
-	free(arg);
-
-	fibril_mutex_lock(&data->hub->pending_ops_mutex);
-	assert(data->hub->pending_ops_count > 0);
-	data->hub->pending_ops_count--;
-	fibril_condvar_signal(&data->hub->pending_ops_cv);
-	fibril_mutex_unlock(&data->hub->pending_ops_mutex);
-
-
-	return EOK;
-}
-
-/** Start device adding when connection change is detected.
- *
- * This fires a new fibril to complete the device addition.
- *
- * @param hub Hub where the change occured.
- * @param port Port index (starting at 1).
- * @param speed Speed of the device.
- * @return Error code.
- */
-static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
-    usb_speed_t speed) {
-	struct add_device_phase1 *data
-	    = malloc(sizeof (struct add_device_phase1));
-	if (data == NULL) {
-		return ENOMEM;
-	}
-	data->hub = hub;
-	data->port = port;
-	data->speed = speed;
-
-	usb_hub_port_t *the_port = hub->ports + port;
-
-	fibril_mutex_lock(&the_port->reset_mutex);
-	the_port->reset_completed = false;
-	fibril_mutex_unlock(&the_port->reset_mutex);
-
-	int rc = usb_hub_clear_port_feature(hub->control_pipe, port,
-	    USB_HUB_FEATURE_C_PORT_CONNECTION);
-	if (rc != EOK) {
-		free(data);
-		usb_log_warning("Failed to clear port change flag: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
-	if (fibril == 0) {
-		free(data);
-		return ENOMEM;
-	}
-	fibril_mutex_lock(&hub->pending_ops_mutex);
-	hub->pending_ops_count++;
-	fibril_mutex_unlock(&hub->pending_ops_mutex);
-	fibril_add_ready(fibril);
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhub/ports.h
===================================================================
--- uspace/drv/usbhub/ports.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,80 +1,0 @@
-/*
- * 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 drvusbhub
- * @{
- */
-/** @file
- * Hub ports related functions.
- */
-#ifndef DRV_USBHUB_PORTS_H
-#define DRV_USBHUB_PORTS_H
-
-#include <usb/dev/driver.h>
-#include <usb/dev/hub.h>
-
-typedef struct usb_hub_info_t usb_hub_info_t;
-
-/** Information about single port on a hub. */
-typedef struct {
-	/** Mutex needed by CV for checking port reset. */
-	fibril_mutex_t reset_mutex;
-	/** CV for waiting to port reset completion. */
-	fibril_condvar_t reset_cv;
-	/** Whether port reset is completed.
-	 * Guarded by @c reset_mutex.
-	 */
-	bool reset_completed;
-	/** Whether to announce the port reset as successful. */
-	bool reset_okay;
-
-	/** Information about attached device. */
-	usb_hc_attached_device_t attached_device;
-} usb_hub_port_t;
-
-/** Initialize hub port information.
- *
- * @param port Port to be initialized.
- */
-static inline void usb_hub_port_init(usb_hub_port_t *port) {
-	port->attached_device.address = -1;
-	port->attached_device.handle = 0;
-	fibril_mutex_initialize(&port->reset_mutex);
-	fibril_condvar_initialize(&port->reset_cv);
-}
-
-
-void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
-	uint16_t port);
-
-
-
-#endif
-/**
- * @}
- */
Index: pace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,522 +1,0 @@
-/*
- * Copyright (c) 2010 Matus Dekanek
- * 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 drvusbhub
- * @{
- */
-/** @file
- * @brief usb hub main functionality
- */
-
-#include <ddf/driver.h>
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <inttypes.h>
-
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
-#include <usb/descriptor.h>
-#include <usb/dev/recognise.h>
-#include <usb/dev/request.h>
-#include <usb/classes/hub.h>
-#include <usb/dev/poll.h>
-#include <stdio.h>
-
-#include "usbhub.h"
-#include "usbhub_private.h"
-#include "port_status.h"
-#include <usb/usb.h>
-#include <usb/dev/pipes.h>
-#include <usb/classes/classes.h>
-
-
-static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev);
-
-static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info);
-
-static int usb_hub_set_configuration(usb_hub_info_t *hub_info);
-
-static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info);
-
-static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
-    usb_hub_status_t status);
-
-static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
-    usb_hub_status_t status);
-
-static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info);
-
-static void usb_hub_polling_terminated_callback(usb_device_t *device,
-    bool was_error, void *data);
-
-
-//*********************************************
-//
-//  hub driver code, initialization
-//
-//*********************************************
-
-/**
- * Initialize hub device driver fibril
- *
- * Creates hub representation and fibril that periodically checks hub`s status.
- * Hub representation is passed to the fibril.
- * @param usb_dev generic usb device information
- * @return error code
- */
-int usb_hub_add_device(usb_device_t *usb_dev) {
-	if (!usb_dev) return EINVAL;
-	usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev);
-	//create hc connection
-	usb_log_debug("Initializing USB wire abstraction.\n");
-	int opResult = usb_hc_connection_initialize_from_device(
-	    &hub_info->connection,
-	    hub_info->usb_device->ddf_dev);
-	if (opResult != EOK) {
-		usb_log_error("Could not initialize connection to device, "
-		    " %s\n",
-		    str_error(opResult));
-		free(hub_info);
-		return opResult;
-	}
-
-	//set hub configuration
-	opResult = usb_hub_set_configuration(hub_info);
-	if (opResult != EOK) {
-		usb_log_error("Could not set hub configuration, %s\n",
-		    str_error(opResult));
-		free(hub_info);
-		return opResult;
-	}
-	//get port count and create attached_devs
-	opResult = usb_hub_process_hub_specific_info(hub_info);
-	if (opResult != EOK) {
-		usb_log_error("Could process hub specific info, %s\n",
-		    str_error(opResult));
-		free(hub_info);
-		return opResult;
-	}
-
-	usb_log_debug("Creating 'hub' function in DDF.\n");
-	ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
-	    fun_exposed, "hub");
-	assert(hub_fun != NULL);
-	hub_fun->ops = NULL;
-
-	opResult = ddf_fun_bind(hub_fun);
-	assert(opResult == EOK);
-	opResult = ddf_fun_add_to_class(hub_fun, "hub");
-	assert(opResult == EOK);
-
-	opResult = usb_hub_start_hub_fibril(hub_info);
-	if (opResult != EOK)
-		free(hub_info);
-	return opResult;
-}
-
-/** Callback for polling hub for changes.
- *
- * @param dev Device where the change occured.
- * @param change_bitmap Bitmap of changed ports.
- * @param change_bitmap_size Size of the bitmap in bytes.
- * @param arg Custom argument, points to @c usb_hub_info_t.
- * @return Whether to continue polling.
- */
-bool hub_port_changes_callback(usb_device_t *dev,
-    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
-	usb_log_debug("hub_port_changes_callback\n");
-	usb_hub_info_t *hub = (usb_hub_info_t *) arg;
-
-	/* FIXME: check that we received enough bytes. */
-	if (change_bitmap_size == 0) {
-		goto leave;
-	}
-
-	bool change;
-	change = ((uint8_t*) change_bitmap)[0] & 1;
-	if (change) {
-		usb_hub_process_global_interrupt(hub);
-	}
-
-	size_t port;
-	for (port = 1; port < hub->port_count + 1; port++) {
-		bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
-		if (change) {
-			usb_hub_process_port_interrupt(hub, port);
-		}
-	}
-leave:
-	/* FIXME: proper interval. */
-	async_usleep(1000 * 250);
-
-	return true;
-}
-
-
-//*********************************************
-//
-//  support functions
-//
-//*********************************************
-
-/**
- * create usb_hub_info_t structure
- *
- * Does only basic copying of known information into new structure.
- * @param usb_dev usb device structure
- * @return basic usb_hub_info_t structure
- */
-static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev) {
-	usb_hub_info_t * result = malloc(sizeof (usb_hub_info_t));
-	if (!result) return NULL;
-	result->usb_device = usb_dev;
-	result->status_change_pipe = usb_dev->pipes[0].pipe;
-	result->control_pipe = &usb_dev->ctrl_pipe;
-	result->is_default_address_used = false;
-
-	result->ports = NULL;
-	result->port_count = (size_t) - 1;
-	fibril_mutex_initialize(&result->port_mutex);
-
-	fibril_mutex_initialize(&result->pending_ops_mutex);
-	fibril_condvar_initialize(&result->pending_ops_cv);
-	result->pending_ops_count = 0;
-	return result;
-}
-
-/**
- * Load hub-specific information into hub_info structure and process if needed
- *
- * Particularly read port count and initialize structure holding port
- * information. If there are non-removable devices, start initializing them.
- * This function is hub-specific and should be run only after the hub is
- * configured using usb_hub_set_configuration function.
- * @param hub_info hub representation
- * @return error code
- */
-static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) {
-	// get hub descriptor
-	usb_log_debug("Creating serialized descriptor\n");
-	uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
-	usb_hub_descriptor_t * descriptor;
-	int opResult;
-
-	size_t received_size;
-	opResult = usb_request_get_descriptor(hub_info->control_pipe,
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
-	    USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
-
-	if (opResult != EOK) {
-		usb_log_error("Failed when receiving hub descriptor, "
-		    "%s\n",
-		    str_error(opResult));
-		free(serialized_descriptor);
-		return opResult;
-	}
-	usb_log_debug2("Deserializing descriptor\n");
-	descriptor = usb_create_deserialized_hub_desriptor(
-	    serialized_descriptor);
-	if (descriptor == NULL) {
-		usb_log_warning("could not deserialize descriptor \n");
-		return ENOMEM;
-	}
-	usb_log_debug("setting port count to %d\n", descriptor->ports_count);
-	hub_info->port_count = descriptor->ports_count;
-	bool is_power_switched =
-	    ((descriptor->hub_characteristics & 1) == 0);
-	bool has_individual_port_powering =
-	    ((descriptor->hub_characteristics & 1) != 0);
-	hub_info->ports = malloc(
-	    sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
-	if (!hub_info->ports) {
-		return ENOMEM;
-	}
-	size_t port;
-	for (port = 0; port < hub_info->port_count + 1; ++port) {
-		usb_hub_port_init(&hub_info->ports[port]);
-	}
-	if (is_power_switched) {
-		usb_log_debug("Hub power switched\n");
-
-		if (!has_individual_port_powering) {
-			//this setting actually makes no difference
-			usb_log_debug("Hub has global powering\n");
-		}
-
-		for (port = 1; port <= hub_info->port_count; ++port) {
-			usb_log_debug("Powering port %zu.\n", port);
-			opResult = usb_hub_set_port_feature(hub_info->control_pipe,
-			    port, USB_HUB_FEATURE_PORT_POWER);
-			if (opResult != EOK) {
-				usb_log_error("Cannot power on port %zu: %s.\n",
-				    port, str_error(opResult));
-			}
-		}
-
-	} else {
-		usb_log_debug("Power not switched, not going to be powered\n");
-	}
-	usb_log_debug2("Freeing data\n");
-	free(descriptor);
-	return EOK;
-}
-
-/**
- * Set configuration of hub
- *
- * Check whether there is at least one configuration and sets the first one.
- * This function should be run prior to running any hub-specific action.
- * @param hub_info hub representation
- * @return error code
- */
-static int usb_hub_set_configuration(usb_hub_info_t *hub_info) {
-	//device descriptor
-	usb_standard_device_descriptor_t *std_descriptor
-	    = &hub_info->usb_device->descriptors.device;
-	usb_log_debug("Hub has %d configurations\n",
-	    std_descriptor->configuration_count);
-	if (std_descriptor->configuration_count < 1) {
-		usb_log_error("There are no configurations available\n");
-		return EINVAL;
-	}
-
-	usb_standard_configuration_descriptor_t *config_descriptor
-	    = (usb_standard_configuration_descriptor_t *)
-	    hub_info->usb_device->descriptors.configuration;
-
-	/* Set configuration. */
-	int opResult = usb_request_set_configuration(
-	    &hub_info->usb_device->ctrl_pipe,
-	    config_descriptor->configuration_number);
-
-	if (opResult != EOK) {
-		usb_log_error("Failed to set hub configuration: %s.\n",
-		    str_error(opResult));
-		return opResult;
-	}
-	usb_log_debug("\tUsed configuration %d\n",
-	    config_descriptor->configuration_number);
-
-	return EOK;
-}
-
-/**
- * create and start fibril with hub control loop
- *
- * Before the fibril is started, the control pipe and host controller
- * connection of the hub is open.
- *
- * @param hub_info hub representing structure
- * @return error code
- */
-static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info) {
-	int rc;
-
-	rc = usb_device_auto_poll(hub_info->usb_device, 0,
-	    hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
-	    usb_hub_polling_terminated_callback, hub_info);
-	if (rc != EOK) {
-		usb_log_error("Failed to create polling fibril: %s.\n",
-		    str_error(rc));
-		free(hub_info);
-		return rc;
-	}
-
-	usb_log_info("Controlling hub `%s' (%zu ports).\n",
-	    hub_info->usb_device->ddf_dev->name, hub_info->port_count);
-	return EOK;
-}
-
-//*********************************************
-//
-//  change handling functions
-//
-//*********************************************
-
-/**
- * process hub over current change
- *
- * This means either to power off the hub or power it on.
- * @param hub_info hub instance
- * @param status hub status bitmask
- * @return error code
- */
-static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
-    usb_hub_status_t status) {
-	int opResult;
-	if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) {
-		//poweroff all ports
-		unsigned int port;
-		for (port = 1; port <= hub_info->port_count; ++port) {
-			opResult = usb_hub_clear_port_feature(
-			    hub_info->control_pipe, port,
-			    USB_HUB_FEATURE_PORT_POWER);
-			if (opResult != EOK) {
-				usb_log_warning(
-				    "Cannot power off port %d;  %s\n",
-				    port, str_error(opResult));
-			}
-		}
-	} else {
-		//power all ports
-		unsigned int port;
-		for (port = 1; port <= hub_info->port_count; ++port) {
-			opResult = usb_hub_set_port_feature(
-			    hub_info->control_pipe, port,
-			    USB_HUB_FEATURE_PORT_POWER);
-			if (opResult != EOK) {
-				usb_log_warning(
-				    "Cannot power off port %d;  %s\n",
-				    port, str_error(opResult));
-			}
-		}
-	}
-	return opResult;
-}
-
-/**
- * process hub local power change
- *
- * This change is ignored.
- * @param hub_info hub instance
- * @param status hub status bitmask
- * @return error code
- */
-static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
-    usb_hub_status_t status) {
-	int opResult = EOK;
-	opResult = usb_hub_clear_feature(hub_info->control_pipe,
-	    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
-	if (opResult != EOK) {
-		usb_log_error("Cannnot clear hub power change flag: "
-		    "%s\n",
-		    str_error(opResult));
-	}
-	return opResult;
-}
-
-/**
- * process hub interrupts
- *
- * The change can be either in the over-current condition or
- * local-power change.
- * @param hub_info hub instance
- */
-static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) {
-	usb_log_debug("Global interrupt on a hub\n");
-	usb_pipe_t *pipe = hub_info->control_pipe;
-	int opResult;
-
-	usb_port_status_t status;
-	size_t rcvd_size;
-	usb_device_request_setup_packet_t request;
-	//int opResult;
-	usb_hub_set_hub_status_request(&request);
-	//endpoint 0
-
-	opResult = usb_pipe_control_read(
-	    pipe,
-	    &request, sizeof (usb_device_request_setup_packet_t),
-	    &status, 4, &rcvd_size
-	    );
-	if (opResult != EOK) {
-		usb_log_error("Could not get hub status: %s\n",
-		    str_error(opResult));
-		return;
-	}
-	if (rcvd_size != sizeof (usb_port_status_t)) {
-		usb_log_error("Received status has incorrect size\n");
-		return;
-	}
-	//port reset
-	if (
-	    usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
-		usb_process_hub_over_current(hub_info, status);
-	}
-	if (
-	    usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
-		usb_process_hub_local_power_change(hub_info, status);
-	}
-}
-
-/**
- * callback called from hub polling fibril when the fibril terminates
- *
- * Should perform a cleanup - deletes hub_info.
- * @param device usb device afected
- * @param was_error indicates that the fibril is stoped due to an error
- * @param data pointer to usb_hub_info_t structure
- */
-static void usb_hub_polling_terminated_callback(usb_device_t *device,
-    bool was_error, void *data) {
-	usb_hub_info_t * hub = data;
-	assert(hub);
-
-	fibril_mutex_lock(&hub->pending_ops_mutex);
-
-	/* The device is dead. However there might be some pending operations
-	 * that we need to wait for.
-	 * One of them is device adding in progress.
-	 * The respective fibril is probably waiting for status change
-	 * in port reset (port enable) callback.
-	 * Such change would never come (otherwise we would not be here).
-	 * Thus, we would flush all pending port resets.
-	 */
-	if (hub->pending_ops_count > 0) {
-		fibril_mutex_lock(&hub->port_mutex);
-		size_t port;
-		for (port = 0; port < hub->port_count; port++) {
-			usb_hub_port_t *the_port = hub->ports + port;
-			fibril_mutex_lock(&the_port->reset_mutex);
-			the_port->reset_completed = true;
-			the_port->reset_okay = false;
-			fibril_condvar_broadcast(&the_port->reset_cv);
-			fibril_mutex_unlock(&the_port->reset_mutex);
-		}
-		fibril_mutex_unlock(&hub->port_mutex);
-	}
-	/* And now wait for them. */
-	while (hub->pending_ops_count > 0) {
-		fibril_condvar_wait(&hub->pending_ops_cv,
-		    &hub->pending_ops_mutex);
-	}
-	fibril_mutex_unlock(&hub->pending_ops_mutex);
-
-	usb_device_destroy(hub->usb_device);
-
-	free(hub->ports);
-	free(hub);
-}
-
-
-
-
-/**
- * @}
- */
Index: pace/drv/usbhub/usbhub.h
===================================================================
--- uspace/drv/usbhub/usbhub.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,114 +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 drvusbhub
- * @{
- */
-/** @file
- * @brief Hub driver.
- */
-#ifndef DRV_USBHUB_USBHUB_H
-#define DRV_USBHUB_USBHUB_H
-
-#include <ipc/devman.h>
-#include <ddf/driver.h>
-
-#include <usb/dev/hub.h>
-#include <usb/classes/hub.h>
-
-#include <usb/dev/pipes.h>
-#include <usb/dev/driver.h>
-
-#include <fibril_synch.h>
-
-#define NAME "usbhub"
-
-#include "ports.h"
-
-/** Information about attached hub. */
-struct usb_hub_info_t {
-	/** Number of ports. */
-	size_t port_count;
-
-	/** attached device handles, for each port one */
-	usb_hub_port_t *ports;
-
-	fibril_mutex_t port_mutex;
-
-	/** connection to hcd */
-	usb_hc_connection_t connection;
-
-	/** default address is used indicator
-	 *
-	 * If default address is requested by this device, it cannot
-	 * be requested by the same hub again, otherwise a deadlock will occur.
-	 */
-	bool is_default_address_used;
-
-	/** convenience pointer to status change pipe
-	 *
-	 * Status change pipe is initialized in usb_device structure. This is
-	 * pointer into this structure, so that it does not have to be
-	 * searched again and again for the 'right pipe'.
-	 */
-	usb_pipe_t * status_change_pipe;
-
-	/** convenience pointer to control pipe
-	 *
-	 * Control pipe is initialized in usb_device structure. This is
-	 * pointer into this structure, so that it does not have to be
-	 * searched again and again for the 'right pipe'.
-	 */
-	usb_pipe_t * control_pipe;
-
-	/** generic usb device data*/
-	usb_device_t * usb_device;
-
-	/** Number of pending operations on the mutex to prevent shooting
-	 * ourselves in the foot.
-	 * When the hub is disconnected but we are in the middle of some
-	 * operation, we cannot destroy this structure right away because
-	 * the pending operation might use it.
-	 */
-	size_t pending_ops_count;
-	/** Guard for pending_ops_count. */
-	fibril_mutex_t pending_ops_mutex;
-	/** Condition variable for pending_ops_count. */
-	fibril_condvar_t pending_ops_cv;
-
-};
-
-int usb_hub_add_device(usb_device_t *usb_dev);
-
-bool hub_port_changes_callback(usb_device_t *dev,
-    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
-
-#endif
-/**
- * @}
- */
Index: pace/drv/usbhub/usbhub.ma
===================================================================
--- uspace/drv/usbhub/usbhub.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,2 +1,0 @@
-10 usb&hub
-10 usb&class=hub
Index: pace/drv/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/usbhub/usbhub_private.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,184 +1,0 @@
-/*
- * Copyright (c) 2010 Matus Dekanek
- * 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 drvusbhub
- * @{
- */
-/** @file
- * @brief Hub driver private definitions
- */
-
-#ifndef USBHUB_PRIVATE_H
-#define	USBHUB_PRIVATE_H
-
-#include "usbhub.h"
-
-#include <adt/list.h>
-#include <bool.h>
-#include <ddf/driver.h>
-#include <fibril_synch.h>
-
-#include <usb/classes/hub.h>
-#include <usb/usb.h>
-#include <usb/debug.h>
-#include <usb/dev/request.h>
-
-//************
-//
-// convenience define for malloc
-//
-//************
-
-
-usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
-
-/**
- * Set the device request to be a get hub descriptor request.
- * @warning the size is allways set to USB_HUB_MAX_DESCRIPTOR_SIZE
- * @param request
- * @param addr
- */
-static inline void usb_hub_set_descriptor_request(
-    usb_device_request_setup_packet_t * request
-    ) {
-	request->index = 0;
-	request->request_type = USB_HUB_REQ_TYPE_GET_DESCRIPTOR;
-	request->request = USB_HUB_REQUEST_GET_DESCRIPTOR;
-	request->value_high = USB_DESCTYPE_HUB;
-	request->value_low = 0;
-	request->length = USB_HUB_MAX_DESCRIPTOR_SIZE;
-}
-
-/**
- * Clear feature on hub port.
- *
- * @param hc Host controller telephone
- * @param address Hub address
- * @param port_index Port
- * @param feature Feature selector
- * @return Operation result
- */
-static inline int usb_hub_clear_port_feature(usb_pipe_t *pipe,
-    int port_index,
-    usb_hub_class_feature_t feature) {
-
-	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
-		.request = USB_DEVREQ_CLEAR_FEATURE,
-		.length = 0,
-		.index = port_index
-	};
-	clear_request.value = feature;
-	return usb_pipe_control_write(pipe, &clear_request,
-	    sizeof (clear_request), NULL, 0);
-}
-
-/**
- * Clear feature on hub port.
- *
- * @param hc Host controller telephone
- * @param address Hub address
- * @param port_index Port
- * @param feature Feature selector
- * @return Operation result
- */
-static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,
-    int port_index,
-    usb_hub_class_feature_t feature) {
-
-	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
-		.request = USB_DEVREQ_SET_FEATURE,
-		.length = 0,
-		.index = port_index
-	};
-	clear_request.value = feature;
-	return usb_pipe_control_write(pipe, &clear_request,
-	    sizeof (clear_request), NULL, 0);
-}
-
-/**
- * Clear feature on hub port.
- *
- * @param pipe pipe to hub control endpoint
- * @param feature Feature selector
- * @return Operation result
- */
-static inline int usb_hub_clear_feature(usb_pipe_t *pipe,
-    usb_hub_class_feature_t feature) {
-
-	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
-		.request = USB_DEVREQ_CLEAR_FEATURE,
-		.length = 0,
-		.index = 0
-	};
-	clear_request.value = feature;
-	return usb_pipe_control_write(pipe, &clear_request,
-	    sizeof (clear_request), NULL, 0);
-}
-
-/**
- * Clear feature on hub port.
- *
- * @param pipe pipe to hub control endpoint
- * @param feature Feature selector
- * @return Operation result
- */
-static inline int usb_hub_set_feature(usb_pipe_t *pipe,
-    usb_hub_class_feature_t feature) {
-
-	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
-		.request = USB_DEVREQ_SET_FEATURE,
-		.length = 0,
-		.index = 0
-	};
-	clear_request.value = feature;
-	return usb_pipe_control_write(pipe, &clear_request,
-	    sizeof (clear_request), NULL, 0);
-}
-
-
-void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t * descriptor);
-
-void usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor,
-    void * serialized_descriptor);
-
-usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
-    void * serialized_descriptor);
-
-void usb_deserialize_hub_desriptor(void * serialized_descriptor,
-    usb_hub_descriptor_t * descriptor);
-
-
-#endif	/* USBHUB_PRIVATE_H */
-
-/**
- * @}
- */
Index: pace/drv/usbhub/utils.c
===================================================================
--- uspace/drv/usbhub/utils.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,163 +1,0 @@
-/*
- * Copyright (c) 2010 Matus Dekanek
- * 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 drvusbhub
- * @{
- */
-/** @file
- * @brief various utilities
- */
-#include <ddf/driver.h>
-#include <bool.h>
-#include <errno.h>
-
-#include <usbhc_iface.h>
-#include <usb/descriptor.h>
-#include <usb/classes/hub.h>
-
-#include "usbhub.h"
-#include "usbhub_private.h"
-#include "port_status.h"
-
-
-size_t USB_HUB_MAX_DESCRIPTOR_SIZE = 71;
-
-//*********************************************
-//
-//  various utils
-//
-//*********************************************
-
-//hub descriptor utils
-
-/**
- * create uint8_t array with serialized descriptor
- *
- * @param descriptor
- * @return newly created serializd descriptor pointer
- */
-void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t *descriptor) {
-	//base size
-	size_t size = 7;
-	//variable size according to port count
-	size_t var_size = (descriptor->ports_count + 7) / 8;
-	size += 2 * var_size;
-	uint8_t * result = malloc(size);
-	//size
-	if (result)
-		usb_serialize_hub_descriptor(descriptor, result);
-	return result;
-}
-
-/**
- * serialize descriptor into given buffer
- *
- * The buffer size is not checked.
- * @param descriptor
- * @param serialized_descriptor
- */
-void usb_serialize_hub_descriptor(usb_hub_descriptor_t *descriptor,
-    void * serialized_descriptor) {
-	//base size
-	uint8_t * sdescriptor = serialized_descriptor;
-	size_t size = 7;
-	//variable size according to port count
-	size_t var_size = (descriptor->ports_count + 7) / 8;
-	size += 2 * var_size;
-	//size
-	sdescriptor[0] = size;
-	//descriptor type
-	sdescriptor[1] = USB_DESCTYPE_HUB;
-	sdescriptor[2] = descriptor->ports_count;
-	/// @fixme handling of endianness??
-	sdescriptor[3] = descriptor->hub_characteristics / 256;
-	sdescriptor[4] = descriptor->hub_characteristics % 256;
-	sdescriptor[5] = descriptor->pwr_on_2_good_time;
-	sdescriptor[6] = descriptor->current_requirement;
-
-	size_t i;
-	for (i = 0; i < var_size; ++i) {
-		sdescriptor[7 + i] = descriptor->devices_removable[i];
-	}
-	for (i = 0; i < var_size; ++i) {
-		sdescriptor[7 + var_size + i] = 255;
-	}
-}
-
-/**
- * create deserialized desriptor structure out of serialized descriptor
- *
- * The serialized descriptor must be proper usb hub descriptor,
- * otherwise an eerror might occur.
- *
- * @param sdescriptor serialized descriptor
- * @return newly created deserialized descriptor pointer
- */
-usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
-    void *serialized_descriptor) {
-	uint8_t * sdescriptor = serialized_descriptor;
-
-	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
-		usb_log_warning("trying to deserialize wrong descriptor %x\n",
-		    sdescriptor[1]);
-		return NULL;
-	}
-
-	usb_hub_descriptor_t * result = malloc(sizeof (usb_hub_descriptor_t));
-	if (result)
-		usb_deserialize_hub_desriptor(serialized_descriptor, result);
-	return result;
-}
-
-/**
- * deserialize descriptor into given pointer
- * 
- * @param serialized_descriptor
- * @param descriptor
- * @return
- */
-void usb_deserialize_hub_desriptor(
-    void * serialized_descriptor, usb_hub_descriptor_t *descriptor) {
-	uint8_t * sdescriptor = serialized_descriptor;
-	descriptor->ports_count = sdescriptor[2];
-	/// @fixme handling of endianness??
-	descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
-	descriptor->pwr_on_2_good_time = sdescriptor[5];
-	descriptor->current_requirement = sdescriptor[6];
-	size_t var_size = (descriptor->ports_count + 7) / 8;
-	//descriptor->devices_removable = (uint8_t*) malloc(var_size);
-
-	size_t i;
-	for (i = 0; i < var_size; ++i) {
-		descriptor->devices_removable[i] = sdescriptor[7 + i];
-	}
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmast/Makefile
===================================================================
--- uspace/drv/usbmast/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,47 +1,0 @@
-#
-# 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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = usbmast
-
-SOURCES = \
-	inquiry.c \
-	main.c \
-	mast.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/usbmast/cmds.h
===================================================================
--- uspace/drv/usbmast/cmds.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * 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 drvusbmast
- * @{
- */
-/** @file
- * USB mass storage commands.
- */
-
-#ifndef USB_USBMAST_CMDS_H_
-#define USB_USBMAST_CMDS_H_
-
-#include <sys/types.h>
-#include <usb/usb.h>
-
-typedef struct {
-	uint32_t dCBWSignature;
-	uint32_t dCBWTag;
-	uint32_t dCBWDataTransferLength;
-	uint8_t bmCBWFlags;
-	uint8_t bCBWLUN;
-	uint8_t bCBWBLength;
-	uint8_t CBWCB[16];
-} __attribute__((packed)) usb_massstor_cbw_t;
-
-typedef struct {
-	uint32_t dCSWSignature;
-	uint32_t dCSWTag;
-	uint32_t dCSWDataResidue;
-	uint8_t dCSWStatus;
-} __attribute__((packed)) usb_massstor_csw_t;
-
-static inline void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw,
-    uint32_t tag, uint32_t transfer_length, usb_direction_t dir,
-    uint8_t lun, uint8_t cmd_len, uint8_t *cmd)
-{
-	cbw->dCBWSignature = uint32_host2usb(0x43425355);
-	cbw->dCBWTag = tag;
-	cbw->dCBWDataTransferLength = transfer_length;
-
-	cbw->bmCBWFlags = 0;
-	if (dir == USB_DIRECTION_IN) {
-		cbw->bmCBWFlags |= (1 << 7);
-	}
-
-	/* Only lowest 4 bits. */
-	cbw->bCBWLUN = lun & 0x0F;
-
-	/* Only lowest 5 bits. */
-	cbw->bCBWBLength = cmd_len & 0x1F;
-
-	memcpy(cbw->CBWCB, cmd, cbw->bCBWBLength);
-}
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/usbmast/inquiry.c
===================================================================
--- uspace/drv/usbmast/inquiry.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,193 +1,0 @@
-/*
- * 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 drvusbmast
- * @{
- */
-/**
- * @file
- * Main routines of USB mass storage driver.
- */
-#include <usb/dev/driver.h>
-#include <usb/debug.h>
-#include <usb/classes/classes.h>
-#include <usb/classes/massstor.h>
-#include <errno.h>
-#include <str_error.h>
-#include <str.h>
-#include <ctype.h>
-#include "cmds.h"
-#include "scsi.h"
-#include "mast.h"
-
-#define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
-#define BITS_GET_MID_MASK(type, bitcount, offset) \
-	((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
-#define BITS_GET(type, number, bitcount, offset) \
-	((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
-
-#define INQUIRY_RESPONSE_LENGTH 36
-
-#define STR_UNKNOWN "<unknown>"
-
-/** String constants for SCSI peripheral device types. */
-static const char *str_peripheral_device_types[] = {
-	"direct-access device",
-	"sequential-access device",
-	"printer device",
-	"processor device",
-	"write-once device",
-	"CDROM device",
-	"scanner device",
-	"optical memory device",
-	"medium changer",
-	"communications device",
-	"graphic arts pre-press device",
-	"graphic arts pre-press device",
-	"storage array controller device",
-	"enclosure services device",
-	"simplified direct-access device",
-	"optical card reader/writer device",
-	"bridging expander",
-	"object-based storage device",
-	"automation driver interface",
-	STR_UNKNOWN, // 0x13
-	STR_UNKNOWN, // 0x14
-	STR_UNKNOWN, // 0x15
-	STR_UNKNOWN, // 0x16
-	STR_UNKNOWN, // 0x17
-	STR_UNKNOWN, // 0x18
-	STR_UNKNOWN, // 0x19
-	STR_UNKNOWN, // 0x1A
-	STR_UNKNOWN, // 0x1B
-	STR_UNKNOWN, // 0x1C
-	STR_UNKNOWN, // 0x1D
-	"well-known logical unit",
-	"uknown or no device state"
-};
-#define str_peripheral_device_types_count \
-	(sizeof(str_peripheral_device_types)/sizeof(str_peripheral_device_types[0]))
-
-/** Get string representation for SCSI peripheral device type.
- *
- * See for example here for a list
- * http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type.
- *
- * @param type SCSI peripheral device type code.
- * @return String representation.
- */
-const char *usb_str_masstor_scsi_peripheral_device_type(int type)
-{
-	if ((type < 0)
-	    || ((size_t)type >= str_peripheral_device_types_count)) {
-		return STR_UNKNOWN;
-	}
-	return str_peripheral_device_types[type];
-}
-
-/** Trim trailing spaces from a string (rewrite with string terminator).
- *
- * @param name String to be trimmed (in-out parameter).
- */
-static void trim_trailing_spaces(char *name)
-{
-	size_t len = str_length(name);
-	while ((len > 0) && isspace((int) name[len - 1])) {
-		name[len - 1] = 0;
-		len--;
-	}
-}
-
-/** Perform SCSI INQUIRY command on USB mass storage device.
- *
- * @param dev USB device.
- * @param bulk_in_idx Index (in dev->pipes) of bulk in pipe.
- * @param bulk_out_idx Index of bulk out pipe.
- * @param inquiry_result Where to store parsed inquiry result.
- * @return Error code.
- */
-int usb_massstor_inquiry(usb_device_t *dev,
-    size_t bulk_in_idx, size_t bulk_out_idx,
-    usb_massstor_inquiry_result_t *inquiry_result)
-{
-	scsi_cmd_inquiry_t inquiry = {
-		.op_code = 0x12,
-		.lun_evpd = 0,
-		.page_code = 0,
-		.alloc_length = host2uint16_t_be(INQUIRY_RESPONSE_LENGTH),
-		.ctrl = 0
-	};
-	size_t response_len;
-	uint8_t response[INQUIRY_RESPONSE_LENGTH];
-
-	int rc;
-
-	rc = usb_massstor_data_in(dev, bulk_in_idx, bulk_out_idx,
-	    0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
-	    response, INQUIRY_RESPONSE_LENGTH, &response_len);
-
-	if (rc != EOK) {
-		usb_log_error("Failed to probe device %s using %s: %s.\n",
-		   dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
-		return rc;
-	}
-
-	if (response_len < 8) {
-		usb_log_error("The SCSI response is too short.\n");
-		return ERANGE;
-	}
-
-	/*
-	 * This is an ugly part of the code. We will parse the returned
-	 * data by hand and try to get as many useful data as possible.
-	 */
-	bzero(inquiry_result, sizeof(*inquiry_result));
-
-	/* This shall be returned by all devices. */
-	inquiry_result->peripheral_device_type
-	    = BITS_GET(uint8_t, response[0], 5, 0);
-	inquiry_result->removable = BITS_GET(uint8_t, response[1], 1, 7);
-
-	if (response_len < 32) {
-		return EOK;
-	}
-
-	str_ncpy(inquiry_result->vendor_id, 9,
-	    (const char *) &response[8], 8);
-	trim_trailing_spaces(inquiry_result->vendor_id);
-
-	str_ncpy(inquiry_result->product_and_revision, 12,
-	    (const char *) &response[16], 11);
-	trim_trailing_spaces(inquiry_result->product_and_revision);
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmast/main.c
===================================================================
--- uspace/drv/usbmast/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,151 +1,0 @@
-/*
- * 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 drvusbmast
- * @{
- */
-/**
- * @file
- * Main routines of USB mass storage driver.
- */
-#include <usb/dev/driver.h>
-#include <usb/debug.h>
-#include <usb/classes/classes.h>
-#include <usb/classes/massstor.h>
-#include <errno.h>
-#include <str_error.h>
-#include "cmds.h"
-#include "scsi.h"
-#include "mast.h"
-
-#define NAME "usbmast"
-
-#define BULK_IN_EP 0
-#define BULK_OUT_EP 1
-
-#define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
-#define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
-
-static usb_endpoint_description_t bulk_in_ep = {
-	.transfer_type = USB_TRANSFER_BULK,
-	.direction = USB_DIRECTION_IN,
-	.interface_class = USB_CLASS_MASS_STORAGE,
-	.interface_subclass = USB_MASSSTOR_SUBCLASS_SCSI,
-	.interface_protocol = USB_MASSSTOR_PROTOCOL_BBB,
-	.flags = 0
-};
-static usb_endpoint_description_t bulk_out_ep = {
-	.transfer_type = USB_TRANSFER_BULK,
-	.direction = USB_DIRECTION_OUT,
-	.interface_class = USB_CLASS_MASS_STORAGE,
-	.interface_subclass = USB_MASSSTOR_SUBCLASS_SCSI,
-	.interface_protocol = USB_MASSSTOR_PROTOCOL_BBB,
-	.flags = 0
-};
-
-usb_endpoint_description_t *mast_endpoints[] = {
-	&bulk_in_ep,
-	&bulk_out_ep,
-	NULL
-};
-
-/** Callback when new device is attached and recognized as a mass storage.
- *
- * @param dev Representation of a the USB device.
- * @return Error code.
- */
-static int usbmast_add_device(usb_device_t *dev)
-{
-	int rc;
-	const char *fun_name = "ctl";
-
-	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
-	    fun_name);
-	if (ctl_fun == NULL) {
-		usb_log_error("Failed to create control function.\n");
-		return ENOMEM;
-	}
-	rc = ddf_fun_bind(ctl_fun);
-	if (rc != EOK) {
-		usb_log_error("Failed to bind control function: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	usb_log_info("Pretending to control mass storage `%s'.\n",
-	    dev->ddf_dev->name);
-	usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
-	    dev->pipes[BULK_IN_EP].pipe->endpoint_no,
-	    (size_t) dev->pipes[BULK_IN_EP].descriptor->max_packet_size);
-	usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
-	    dev->pipes[BULK_OUT_EP].pipe->endpoint_no,
-	    (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
-
-	size_t lun_count = usb_masstor_get_lun_count(dev);
-
-	usb_massstor_inquiry_result_t inquiry;
-	rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry);
-	if (rc != EOK) {
-		usb_log_warning("Failed to inquiry device `%s': %s.\n",
-		    dev->ddf_dev->name, str_error(rc));
-		return EOK;
-	}
-
-	usb_log_info("Mass storage `%s': " \
-	    "`%s' by `%s' is %s (%s), %zu LUN(s).\n",
-	    dev->ddf_dev->name,
-	    inquiry.product_and_revision, inquiry.vendor_id,
-	    usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type),
-	    inquiry.removable ? "removable" : "non-removable",
-	    lun_count);
-
-	return EOK;
-}
-
-/** USB mass storage driver ops. */
-static usb_driver_ops_t usbmast_driver_ops = {
-	.add_device = usbmast_add_device,
-};
-
-/** USB mass storage driver. */
-static usb_driver_t usbmast_driver = {
-	.name = NAME,
-	.ops = &usbmast_driver_ops,
-	.endpoints = mast_endpoints
-};
-
-int main(int argc, char *argv[])
-{
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-
-	return usb_driver_main(&usbmast_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmast/mast.c
===================================================================
--- uspace/drv/usbmast/mast.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,222 +1,0 @@
-/*
- * 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 drvusbmast
- * @{
- */
-/**
- * @file
- * Generic functions for USB mass storage (implementation).
- */
-#include "mast.h"
-#include "cmds.h"
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <usb/debug.h>
-#include <usb/dev/request.h>
-
-bool usb_mast_verbose = true;
-
-#define MASTLOG(format, ...) \
-	do { \
-		if (usb_mast_verbose) { \
-			usb_log_debug("USB cl08: " format, ##__VA_ARGS__); \
-		} \
-	} while (false)
-
-/** Request data from mass storage device.
- *
- * @param bulk_in_pipe Bulk in pipe to the device.
- * @param bulk_out_pipe Bulk out pipe to the device.
- * @param tag Command block wrapper tag (automatically compared with answer).
- * @param lun LUN index.
- * @param cmd SCSI command buffer (in SCSI endianness).
- * @param cmd_size Length of SCSI command @p cmd in bytes.
- * @param in_buffer Buffer where to store the answer (CSW is not returned).
- * @param in_buffer_size Size of the buffer (size of the request to the device).
- * @param received_size Number of actually received bytes.
- * @return Error code.
- */
-int usb_massstor_data_in(usb_device_t *dev,
-    size_t bulk_in_pipe_index, size_t bulk_out_pipe_index,
-    uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
-    void *in_buffer, size_t in_buffer_size, size_t *received_size)
-{
-	int rc;
-	size_t act_size;
-	usb_pipe_t *bulk_in_pipe = dev->pipes[bulk_in_pipe_index].pipe;
-	usb_pipe_t *bulk_out_pipe = dev->pipes[bulk_out_pipe_index].pipe;
-
-	/* Prepare CBW - command block wrapper */
-	usb_massstor_cbw_t cbw;
-	usb_massstor_cbw_prepare(&cbw, tag, in_buffer_size,
-	    USB_DIRECTION_IN, lun, cmd_size, cmd);
-
-	/* First, send the CBW. */
-	rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
-	MASTLOG("CBW '%s' sent: %s.\n",
-	    usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
-	    str_error(rc));
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Try to retrieve the data from the device. */
-	act_size = 0;
-	rc = usb_pipe_read(bulk_in_pipe, in_buffer, in_buffer_size, &act_size);
-	MASTLOG("Received %zuB (%s): %s.\n", act_size,
-	    usb_debug_str_buffer((uint8_t *) in_buffer, act_size, 0),
-	    str_error(rc));
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Read CSW. */
-	usb_massstor_csw_t csw;
-	size_t csw_size;
-	rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
-	MASTLOG("CSW '%s' received (%zuB): %s.\n",
-	    usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
-	    str_error(rc));
-	if (rc != EOK) {
-		return rc;
-	}
-	if (csw_size != sizeof(csw)) {
-		return ERANGE;
-	}
-
-	if (csw.dCSWTag != tag) {
-		return EBADCHECKSUM;
-	}
-
-	/*
-	 * Determine the actual return value from the CSW.
-	 */
-	if (csw.dCSWStatus != 0) {
-		// FIXME: better error code
-		// FIXME: distinguish 0x01 and 0x02
-		return EXDEV;
-	}
-
-	size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
-	if (residue > in_buffer_size) {
-		return ERANGE;
-	}
-	if (act_size != in_buffer_size - residue) {
-		return ERANGE;
-	}
-	if (received_size != NULL) {
-		*received_size = in_buffer_size - residue;
-	}
-
-	return EOK;
-}
-
-/** Perform bulk-only mass storage reset.
- *
- * @param dev Device to be reseted.
- * @return Error code.
- */
-int usb_massstor_reset(usb_device_t *dev)
-{
-	return usb_control_request_set(&dev->ctrl_pipe,
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
-	    0xFF, 0, dev->interface_no, NULL, 0);
-}
-
-/** Perform complete reset recovery of bulk-only mass storage.
- *
- * Notice that no error is reported because if this fails, the error
- * would reappear on next transaction somehow.
- *
- * @param dev Device to be reseted.
- * @param bulk_in_idx Index of bulk in pipe.
- * @param bulk_out_idx Index of bulk out pipe.
- */
-void usb_massstor_reset_recovery(usb_device_t *dev,
-    size_t bulk_in_idx, size_t bulk_out_idx)
-{
-	/* We would ignore errors here because if this fails
-	 * we are doomed anyway and any following transaction would fail.
-	 */
-	usb_massstor_reset(dev);
-	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_in_idx].pipe);
-	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_out_idx].pipe);
-}
-
-/** Get max LUN of a mass storage device.
- *
- * @see usb_masstor_get_lun_count
- *
- * @warning Error from this command does not necessarily indicate malfunction
- * of the device. Device does not need to support this request.
- * You shall rather use usb_masstor_get_lun_count.
- *
- * @param dev Mass storage device.
- * @return Error code of maximum LUN (index, not count).
- */
-int usb_massstor_get_max_lun(usb_device_t *dev)
-{
-	uint8_t max_lun;
-	size_t data_recv_len;
-	int rc = usb_control_request_get(&dev->ctrl_pipe,
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
-	    0xFE, 0, dev->interface_no, &max_lun, 1, &data_recv_len);
-	if (rc != EOK) {
-		return rc;
-	}
-	if (data_recv_len != 1) {
-		return EEMPTY;
-	}
-	return (int) max_lun;
-}
-
-/** Get number of LUNs supported by mass storage device.
- *
- * @warning This function hides any error during the request
- * (typically that shall not be a problem).
- *
- * @param dev Mass storage device.
- * @return Number of LUNs.
- */
-size_t usb_masstor_get_lun_count(usb_device_t *dev)
-{
-	int max_lun = usb_massstor_get_max_lun(dev);
-	if (max_lun < 0) {
-		max_lun = 1;
-	} else {
-		max_lun++;
-	}
-
-	return (size_t) max_lun;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmast/mast.h
===================================================================
--- uspace/drv/usbmast/mast.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * 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 drvusbmast
- * @{
- */
-/** @file
- * Generic functions for USB mass storage.
- */
-
-#ifndef USB_USBMAST_MAST_H_
-#define USB_USBMAST_MAST_H_
-
-#include <sys/types.h>
-#include <usb/usb.h>
-#include <usb/dev/pipes.h>
-#include <usb/dev/driver.h>
-
-/** Result of SCSI INQUIRY command.
- * This is already parsed structure, not the original buffer returned by
- * the device.
- */
-typedef struct {
-	/** SCSI peripheral device type. */
-	int peripheral_device_type;
-	/** Whether the device is removable. */
-	bool removable;
-	/** Vendor ID string. */
-	char vendor_id[9];
-	/** Product ID and product revision string. */
-	char product_and_revision[12];
-} usb_massstor_inquiry_result_t;
-
-int usb_massstor_data_in(usb_device_t *dev, size_t, size_t,
-    uint32_t, uint8_t, void *, size_t, void *, size_t, size_t *);
-int usb_massstor_reset(usb_device_t *);
-void usb_massstor_reset_recovery(usb_device_t *, size_t, size_t);
-int usb_massstor_get_max_lun(usb_device_t *);
-size_t usb_masstor_get_lun_count(usb_device_t *);
-int usb_massstor_inquiry(usb_device_t *, size_t, size_t,
-    usb_massstor_inquiry_result_t *);
-const char *usb_str_masstor_scsi_peripheral_device_type(int);
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/usbmast/scsi.h
===================================================================
--- uspace/drv/usbmast/scsi.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * 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 drvusbmast
- * @{
- */
-/** @file
- * SCSI related structures.
- */
-
-#ifndef USB_USBMAST_SCSI_H_
-#define USB_USBMAST_SCSI_H_
-
-#include <sys/types.h>
-#include <usb/usb.h>
-
-typedef struct {
-	uint8_t op_code;
-	uint8_t lun_evpd;
-	uint8_t page_code;
-	uint16_t alloc_length;
-	uint8_t ctrl;
-} __attribute__((packed)) scsi_cmd_inquiry_t;
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/usbmast/usbmast.ma
===================================================================
--- uspace/drv/usbmast/usbmast.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-50 usb&interface&class=mass-storage&subclass=0x06&protocol=0x50
Index: pace/drv/usbmid/Makefile
===================================================================
--- uspace/drv/usbmid/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,48 +1,0 @@
-#
-# 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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-	
-BINARY = usbmid
-
-SOURCES = \
-	dump.c \
-	explore.c \
-	main.c \
-	usbmid.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/usbmid/dump.c
===================================================================
--- uspace/drv/usbmid/dump.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,120 +1,0 @@
-/*
- * 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 drvusbmid
- * @{
- */
-/**
- * @file
- * Dumping and debugging functions.
- */
-#include <errno.h>
-#include <str_error.h>
-#include <stdlib.h>
-#include <usb/dev/pipes.h>
-#include <usb/dev/dp.h>
-#include <usb/classes/classes.h>
-#include "usbmid.h"
-
-/** Dump found descriptor.
- *
- * @param data Descriptor data.
- * @param depth Nesting depth.
- */
-static void dump_tree_descriptor(uint8_t *data, size_t depth)
-{
-	if (data == NULL) {
-		return;
-	}
-	int type = (int) *(data + 1);
-	if (type == USB_DESCTYPE_INTERFACE) {
-		usb_standard_interface_descriptor_t *descriptor
-		    = (usb_standard_interface_descriptor_t *) data;
-		usb_log_info("Found interface: %s (0x%02x/0x%02x/0x%02x).\n",
-		    usb_str_class(descriptor->interface_class),
-		    (int) descriptor->interface_class,
-		    (int) descriptor->interface_subclass,
-		    (int) descriptor->interface_protocol);
-	}
-}
-
-/** Dump tree of descriptors.
- *
- * @param parser Descriptor parser.
- * @param data Descriptor parser data.
- * @param root Pointer to current root.
- * @param depth Nesting depth.
- */
-static void dump_tree_internal(usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
-    uint8_t *root, size_t depth)
-{
-	if (root == NULL) {
-		return;
-	}
-	dump_tree_descriptor(root, depth);
-	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
-	do {
-		dump_tree_internal(parser, data, child, depth + 1);
-		child = usb_dp_get_sibling_descriptor(parser, data, root, child);
-	} while (child != NULL);
-}
-
-/** Dump descriptor tree.
- *
- * @param parser Descriptor parser.
- * @param data Descriptor parser data.
- */
-static void dump_tree(usb_dp_parser_t *parser, usb_dp_parser_data_t *data)
-{
-	uint8_t *ptr = data->data;
-	dump_tree_internal(parser, data, ptr, 0);
-}
-
-/** Dump given descriptors.
- *
- * @param descriptors Descriptors buffer (typically full config descriptor).
- * @param length Size of @p descriptors buffer in bytes.
- */
-void usbmid_dump_descriptors(uint8_t *descriptors, size_t length)
-{
-	usb_dp_parser_data_t data = {
-		.data = descriptors,
-		.size = length,
-		.arg = NULL
-	};
-
-	usb_dp_parser_t parser = {
-		.nesting = usb_dp_standard_descriptor_nesting
-	};
-
-	dump_tree(&parser, &data);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmid/explore.c
===================================================================
--- uspace/drv/usbmid/explore.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,211 +1,0 @@
-/*
- * 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 drvusbmid
- * @{
- */
-/**
- * @file
- * Exploration of available interfaces in the USB device.
- */
-#include <errno.h>
-#include <str_error.h>
-#include <stdlib.h>
-#include <usb/classes/classes.h>
-#include <usb/dev/request.h>
-#include <usb/dev/dp.h>
-#include <usb/ddfiface.h>
-#include "usbmid.h"
-
-/** Operations of the device itself. */
-static ddf_dev_ops_t mid_device_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
-};
-
-/** Tell whether given interface is already in the list.
- *
- * @param list List of usbmid_interface_t members to be searched.
- * @param interface_no Interface number caller is looking for.
- * @return Interface @p interface_no is already present in the list.
- */
-static bool interface_in_list(link_t *list, int interface_no)
-{
-	link_t *l;
-	for (l = list->next; l != list; l = l->next) {
-		usbmid_interface_t *iface
-		    = list_get_instance(l, usbmid_interface_t, link);
-		if (iface->interface_no == interface_no) {
-			return true;
-		}
-	}
-
-	return false;
-}
-
-/** Create list of interfaces from configuration descriptor.
- *
- * @param config_descriptor Configuration descriptor.
- * @param config_descriptor_size Size of configuration descriptor in bytes.
- * @param list List where to add the interfaces.
- */
-static void create_interfaces(uint8_t *config_descriptor,
-    size_t config_descriptor_size, link_t *list)
-{
-	usb_dp_parser_data_t data = {
-		.data = config_descriptor,
-		.size = config_descriptor_size,
-		.arg = NULL
-	};
-
-	usb_dp_parser_t parser = {
-		.nesting = usb_dp_standard_descriptor_nesting
-	};
-
-	uint8_t *interface_ptr = usb_dp_get_nested_descriptor(&parser, &data,
-	    data.data);
-	if (interface_ptr == NULL) {
-		return;
-	}
-
-	do {
-		if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) {
-			goto next_descriptor;
-		}
-
-		usb_standard_interface_descriptor_t *interface
-		    = (usb_standard_interface_descriptor_t *) interface_ptr;
-
-		/* Skip alternate interfaces. */
-		if (!interface_in_list(list, interface->interface_number)) {
-			usbmid_interface_t *iface
-			    = malloc(sizeof(usbmid_interface_t));
-			if (iface == NULL) {
-				break;
-			}
-			link_initialize(&iface->link);
-			iface->fun = NULL;
-			iface->interface_no = interface->interface_number;
-			iface->interface = interface;
-
-			list_append(&iface->link, list);
-		}
-
-		/* TODO: add the alternatives and create match ids from them
-		 * as well.
-		 */
-
-next_descriptor:
-		interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data,
-		    data.data, interface_ptr);
-
-	} while (interface_ptr != NULL);
-
-}
-
-/** Explore MID device.
- *
- * We expect that @p dev is initialized and session on control pipe is
- * started.
- *
- * @param dev Device to be explored.
- * @return Whether to accept this device from devman.
- */
-bool usbmid_explore_device(usb_device_t *dev)
-{
-	int rc;
-
-	int dev_class = dev->descriptors.device.device_class;
-	if (dev_class != USB_CLASS_USE_INTERFACE) {
-		usb_log_warning(
-		    "Device class: %d (%s), but expected class 0.\n",
-		    dev_class, usb_str_class(dev_class));
-		usb_log_error("Not multi interface device, refusing.\n");
-		return false;
-	}
-
-	/* Short cuts to save on typing ;-). */
-	uint8_t *config_descriptor_raw = dev->descriptors.configuration;
-	size_t config_descriptor_size = dev->descriptors.configuration_size;
-	usb_standard_configuration_descriptor_t *config_descriptor =
-	    (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
-
-	/* Select the first configuration */
-	rc = usb_request_set_configuration(&dev->ctrl_pipe,
-	    config_descriptor->configuration_number);
-	if (rc != EOK) {
-		usb_log_error("Failed to set device configuration: %s.\n",
-		    str_error(rc));
-		return false;
-	}
-
-	/* Create control function */
-	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
-	if (ctl_fun == NULL) {
-		usb_log_error("Failed to create control function.\n");
-		return false;
-	}
-
-	ctl_fun->ops = &mid_device_ops;
-
-	rc = ddf_fun_bind(ctl_fun);
-	if (rc != EOK) {
-		usb_log_error("Failed to bind control function: %s.\n",
-		    str_error(rc));
-		return false;
-	}
-
-	/* Create interface children. */
-	link_t interface_list;
-	list_initialize(&interface_list);
-	create_interfaces(config_descriptor_raw, config_descriptor_size,
-	    &interface_list);
-
-	link_t *link;
-	for (link = interface_list.next; link != &interface_list;
-	    link = link->next) {
-		usbmid_interface_t *iface = list_get_instance(link,
-		    usbmid_interface_t, link);
-
-		usb_log_info("Creating child for interface %d (%s).\n",
-		    (int) iface->interface_no,
-		    usb_str_class(iface->interface->interface_class));
-
-		rc = usbmid_spawn_interface_child(dev, iface,
-		    &dev->descriptors.device, iface->interface);
-		if (rc != EOK) {
-			usb_log_error("Failed to create interface child: %s.\n",
-			    str_error(rc));
-		}
-	}
-
-	return true;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmid/main.c
===================================================================
--- uspace/drv/usbmid/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,91 +1,0 @@
-/*
- * 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 drvusbmid
- * @{
- */
-/**
- * @file
- * Main routines of USB multi interface device driver.
- */
-#include <errno.h>
-#include <str_error.h>
-#include <usb/debug.h>
-#include <usb/classes/classes.h>
-#include <usb/dev/request.h>
-#include <usb/descriptor.h>
-#include <usb/dev/pipes.h>
-
-#include "usbmid.h"
-
-/** Callback when new MID device is attached to the host.
- *
- * @param gen_dev Generic DDF device representing the new device.
- * @return Error code.
- */
-static int usbmid_add_device(usb_device_t *dev)
-{
-	usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
-
-	usb_pipe_start_long_transfer(&dev->ctrl_pipe);
-
-	bool accept = usbmid_explore_device(dev);
-
-	usb_pipe_end_long_transfer(&dev->ctrl_pipe);
-
-	if (!accept) {
-		return ENOTSUP;
-	}
-
-	return EOK;
-}
-
-/** USB MID driver ops. */
-static usb_driver_ops_t mid_driver_ops = {
-	.add_device = usbmid_add_device,
-};
-
-/** USB MID driver. */
-static usb_driver_t mid_driver = {
-	.name = NAME,
-	.ops = &mid_driver_ops,
-	.endpoints = NULL
-};
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": USB multi interface device driver.\n");
-
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-
-	return usb_driver_main(&mid_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmid/usbmid.c
===================================================================
--- uspace/drv/usbmid/usbmid.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,152 +1,0 @@
-/*
- * 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 drvusbmid
- * @{
- */
-/**
- * @file
- * Helper functions.
- */
-#include <errno.h>
-#include <str_error.h>
-#include <stdlib.h>
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
-#include <usb/dev/pipes.h>
-#include <usb/classes/classes.h>
-#include <usb/dev/recognise.h>
-#include "usbmid.h"
-
-/** Callback for DDF USB interface. */
-static int usb_iface_get_address_impl(ddf_fun_t *fun, devman_handle_t handle,
-    usb_address_t *address)
-{
-	return usb_iface_get_address_hub_impl(fun, handle, address);
-}
-
-/** Callback for DDF USB interface. */
-static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle,
-    int *iface_no)
-{
-	assert(fun);
-
-	usbmid_interface_t *iface = fun->driver_data;
-	assert(iface);
-
-	if (iface_no != NULL) {
-		*iface_no = iface->interface_no;
-	}
-
-	return EOK;
-}
-
-/** DDF interface of the child - interface function. */
-static usb_iface_t child_usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
-	.get_address = usb_iface_get_address_impl,
-	.get_interface = usb_iface_get_interface_impl
-};
-
-/** Operations for children - interface functions. */
-static ddf_dev_ops_t child_device_ops = {
-	.interfaces[USB_DEV_IFACE] = &child_usb_iface
-};
-
-
-/** Spawn new child device from one interface.
- *
- * @param parent Parent MID device.
- * @param iface Interface information.
- * @param device_descriptor Device descriptor.
- * @param interface_descriptor Interface descriptor.
- * @return Error code.
- */
-int usbmid_spawn_interface_child(usb_device_t *parent,
-    usbmid_interface_t *iface,
-    const usb_standard_device_descriptor_t *device_descriptor,
-    const usb_standard_interface_descriptor_t *interface_descriptor)
-{
-	ddf_fun_t *child = NULL;
-	char *child_name = NULL;
-	int rc;
-
-	/*
-	 * Name is class name followed by interface number.
-	 * The interface number shall provide uniqueness while the
-	 * class name something humanly understandable.
-	 */
-	rc = asprintf(&child_name, "%s%d",
-	    usb_str_class(interface_descriptor->interface_class),
-	    (int) interface_descriptor->interface_number);
-	if (rc < 0) {
-		goto error_leave;
-	}
-
-	/* Create the device. */
-	child = ddf_fun_create(parent->ddf_dev, fun_inner, child_name);
-	if (child == NULL) {
-		rc = ENOMEM;
-		goto error_leave;
-	}
-
-	iface->fun = child;
-
-	child->driver_data = iface;
-	child->ops = &child_device_ops;
-
-	rc = usb_device_create_match_ids_from_interface(device_descriptor,
-	    interface_descriptor,
-	    &child->match_ids);
-	if (rc != EOK) {
-		goto error_leave;
-	}
-
-	rc = ddf_fun_bind(child);
-	if (rc != EOK) {
-		goto error_leave;
-	}
-
-	return EOK;
-
-error_leave:
-	if (child != NULL) {
-		child->name = NULL;
-		/* This takes care of match_id deallocation as well. */
-		ddf_fun_destroy(child);
-	}
-	if (child_name != NULL) {
-		free(child_name);
-	}
-
-	return rc;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmid/usbmid.h
===================================================================
--- uspace/drv/usbmid/usbmid.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/*
- * 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 drvusbmid
- * @{
- */
-/** @file
- * Common definitions.
- */
-
-#ifndef USBMID_H_
-#define USBMID_H_
-
-#include <adt/list.h>
-#include <ddf/driver.h>
-#include <usb/usb.h>
-#include <usb/dev/pipes.h>
-#include <usb/debug.h>
-#include <usb/dev/driver.h>
-
-#define NAME "usbmid"
-
-/** Container for single interface in a MID device. */
-typedef struct {
-	/** Function container. */
-	ddf_fun_t *fun;
-	/** Interface descriptor. */
-	usb_standard_interface_descriptor_t *interface;
-	/** Interface number. */
-	int interface_no;
-	/** List link. */
-	link_t link;
-} usbmid_interface_t;
-
-bool usbmid_explore_device(usb_device_t *);
-int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t *,
-    const usb_standard_device_descriptor_t *,
-    const usb_standard_interface_descriptor_t *);
-void usbmid_dump_descriptors(uint8_t *, size_t);
-
-#endif
-/**
- * @}
- */
Index: pace/drv/usbmid/usbmid.ma
===================================================================
--- uspace/drv/usbmid/usbmid.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-100 usb&mid
Index: pace/drv/usbmouse/Makefile
===================================================================
--- uspace/drv/usbmouse/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,49 +1,0 @@
-#
-# 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.
-#
-
-USPACE_PREFIX = ../..
-
-LIBS = \
-	$(LIBUSBHID_PREFIX)/libusbhid.a \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBUSBHID_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-
-BINARY = usbmouse
-
-SOURCES = \
-	init.c \
-	main.c \
-	mouse.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/usbmouse/init.c
===================================================================
--- uspace/drv/usbmouse/init.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,141 +1,0 @@
-/*
- * 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 drvusbmouse
- * @{
- */
-/**
- * @file
- * Initialization routines for USB mouse driver.
- */
-
-#include "mouse.h"
-#include <usb/debug.h>
-#include <usb/classes/classes.h>
-#include <usb/hid/hid.h>
-#include <usb/dev/request.h>
-#include <usb/hid/request.h>
-#include <errno.h>
-
-/** Mouse polling endpoint description for boot protocol subclass. */
-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_MOUSE,
-	.flags = 0
-};
-
-/** Default handler for IPC methods not handled by DDF.
- *
- * @param fun     Device function handling the call.
- * @param icallid Call ID.
- * @param icall   Call data.
- *
- */
-static void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid,
-    ipc_call_t *icall)
-{
-	usb_mouse_t *mouse = (usb_mouse_t *) fun->driver_data;
-	assert(mouse != NULL);
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
-	
-	if (callback) {
-		if (mouse->console_sess == NULL) {
-			mouse->console_sess = callback;
-			async_answer_0(icallid, EOK);
-		} else
-			async_answer_0(icallid, ELIMIT);
-	} else
-		async_answer_0(icallid, EINVAL);
-}
-
-/** Device ops for USB mouse. */
-static ddf_dev_ops_t mouse_ops = {
-	.default_handler = default_connection_handler
-};
-
-/** Create USB mouse device.
- *
- * The mouse device is stored into <code>dev-&gt;driver_data</code>.
- *
- * @param dev Generic device.
- * @return Error code.
- */
-int usb_mouse_create(usb_device_t *dev)
-{
-	usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
-	if (mouse == NULL)
-		return ENOMEM;
-	
-	mouse->dev = dev;
-	mouse->console_sess = NULL;
-	
-	int rc;
-	
-	/* Create DDF function. */
-	mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse");
-	if (mouse->mouse_fun == NULL) {
-		rc = ENOMEM;
-		goto leave;
-	}
-	
-	mouse->mouse_fun->ops = &mouse_ops;
-	
-	rc = ddf_fun_bind(mouse->mouse_fun);
-	if (rc != EOK)
-		goto leave;
-	
-	/* Add the function to mouse class. */
-	rc = ddf_fun_add_to_class(mouse->mouse_fun, "mouse");
-	if (rc != EOK)
-		goto leave;
-	
-	/* Set the boot protocol. */
-	rc = usbhid_req_set_protocol(&dev->ctrl_pipe, dev->interface_no,
-	    USB_HID_PROTOCOL_BOOT);
-	if (rc != EOK)
-		goto leave;
-	
-	/* Everything allright. */
-	dev->driver_data = mouse;
-	mouse->mouse_fun->driver_data = mouse;
-	
-	return EOK;
-	
-leave:
-	free(mouse);
-	return rc;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmouse/main.c
===================================================================
--- uspace/drv/usbmouse/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,105 +1,0 @@
-/*
- * 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 drvusbmouse
- * @{
- */
-/**
- * @file
- * Main routines of USB boot protocol mouse driver.
- */
-
-#include "mouse.h"
-#include <usb/debug.h>
-#include <usb/dev/poll.h>
-#include <errno.h>
-#include <str_error.h>
-
-#define NAME  "usbmouse"
-
-/** Callback when new mouse device is attached and recognised by DDF.
- *
- * @param dev Representation of a generic DDF device.
- *
- * @return Error code.
- *
- */
-static int usbmouse_add_device(usb_device_t *dev)
-{
-	int rc = usb_mouse_create(dev);
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize device driver: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	usb_log_debug("Polling pipe at endpoint %d.\n",
-	    dev->pipes[0].pipe->endpoint_no);
-	
-	rc = usb_device_auto_poll(dev, 0, usb_mouse_polling_callback,
-	    dev->pipes[0].pipe->max_packet_size,
-	    usb_mouse_polling_ended_callback, dev->driver_data);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to start polling fibril: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	usb_log_info("controlling new mouse (handle %" PRIun ").\n",
-	    dev->ddf_dev->handle);
-	
-	return EOK;
-}
-
-/** USB mouse driver ops. */
-static usb_driver_ops_t mouse_driver_ops = {
-	.add_device = usbmouse_add_device,
-};
-
-static usb_endpoint_description_t *endpoints[] = {
-	&poll_endpoint_description,
-	NULL
-};
-
-/** USB mouse driver. */
-static usb_driver_t mouse_driver = {
-	.name = NAME,
-	.ops = &mouse_driver_ops,
-	.endpoints = endpoints
-};
-
-int main(int argc, char *argv[])
-{
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-	return usb_driver_main(&mouse_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmouse/mouse.c
===================================================================
--- uspace/drv/usbmouse/mouse.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,131 +1,0 @@
-/*
- * 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 drvusbmouse
- * @{
- */
-/**
- * @file
- * Actual handling of USB mouse protocol.
- */
-
-#include <usb/debug.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ipc/mouse.h>
-#include <async.h>
-#include "mouse.h"
-
-/** Mouse polling callback.
- *
- * @param dev    Device that is being polled.
- * @param buffer Data buffer.
- * @param size   Buffer size in bytes.
- * @param arg    Pointer to usb_mouse_t.
- *
- * @return Always true.
- *
- */
-bool usb_mouse_polling_callback(usb_device_t *dev, uint8_t *buffer,
-    size_t size, void *arg)
-{
-	usb_mouse_t *mouse = (usb_mouse_t *) arg;
-	
-	usb_log_debug2("got buffer: %s.\n",
-	    usb_debug_str_buffer(buffer, size, 0));
-	
-	uint8_t butt = buffer[0];
-	char str_buttons[4] = {
-		butt & 1 ? '#' : '.',
-		butt & 2 ? '#' : '.',
-		butt & 4 ? '#' : '.',
-		0
-	};
-	
-	int shift_x = ((int) buffer[1]) - 127;
-	int shift_y = ((int) buffer[2]) - 127;
-	int wheel = ((int) buffer[3]) - 127;
-	
-	if (buffer[1] == 0)
-		shift_x = 0;
-	
-	if (buffer[2] == 0)
-		shift_y = 0;
-	
-	if (buffer[3] == 0)
-		wheel = 0;
-	
-	if (mouse->console_sess) {
-		if ((shift_x != 0) || (shift_y != 0)) {
-			// FIXME: guessed for QEMU
-			
-			async_exch_t *exch = async_exchange_begin(mouse->console_sess);
-			async_req_2_0(exch, MEVENT_MOVE, -shift_x / 10, -shift_y / 10);
-			async_exchange_end(exch);
-		}
-		if (butt) {
-			// FIXME: proper button clicking
-			
-			async_exch_t *exch = async_exchange_begin(mouse->console_sess);
-			async_req_2_0(exch, MEVENT_BUTTON, 1, 1);
-			async_req_2_0(exch, MEVENT_BUTTON, 1, 0);
-			async_exchange_end(exch);
-		}
-	}
-	
-	usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
-	    str_buttons, shift_x, shift_y, wheel);
-	
-	/* Guess. */
-	async_usleep(1000);
-	
-	return true;
-}
-
-/** Callback when polling is terminated.
- *
- * @param dev              Device where the polling terminated.
- * @param recurring_errors Whether the polling was terminated due to
- *                         recurring errors.
- * @param arg              Pointer to usb_mouse_t.
- *
- */
-void usb_mouse_polling_ended_callback(usb_device_t *dev, bool recurring_errors,
-    void *arg)
-{
-	usb_mouse_t *mouse = (usb_mouse_t *) arg;
-	
-	async_hangup(mouse->console_sess);
-	mouse->console_sess = NULL;
-	
-	usb_device_destroy(dev);
-}
-
-/**
- * @}
- */
Index: pace/drv/usbmouse/mouse.h
===================================================================
--- uspace/drv/usbmouse/mouse.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,74 +1,0 @@
-/*
- * 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 drvusbmouse
- * @{
- */
-/**
- * @file
- * Common definitions for USB mouse driver.
- */
-
-#ifndef USBMOUSE_MOUSE_H_
-#define USBMOUSE_MOUSE_H_
-
-#include <usb/dev/driver.h>
-#include <usb/dev/pipes.h>
-#include <time.h>
-#include <async.h>
-
-#define POLL_PIPE(dev) \
-	((dev)->pipes[0].pipe)
-
-/** Container for USB mouse device. */
-typedef struct {
-	/** Generic device container. */
-	usb_device_t *dev;
-	
-	/** Function representing the device. */
-	ddf_fun_t *mouse_fun;
-	
-	/** Polling interval in microseconds. */
-	suseconds_t poll_interval_us;
-	
-	/** Callback session to console (consumer). */
-	async_sess_t *console_sess;
-} usb_mouse_t;
-
-extern usb_endpoint_description_t poll_endpoint_description;
-
-extern int usb_mouse_create(usb_device_t *);
-extern bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t,
-    void *);
-extern void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *);
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/usbmouse/usbmouse.ma
===================================================================
--- uspace/drv/usbmouse/usbmouse.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,1 +1,0 @@
-100 usb&interface&class=HID&subclass=0x01&protocol=0x02
Index: pace/drv/vhc/Makefile
===================================================================
--- uspace/drv/vhc/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,55 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = \
-	$(LIBUSBDEV_PREFIX)/libusbdev.a \
-	$(LIBUSBHOST_PREFIX)/libusbhost.a \
-	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBUSBVIRT_PREFIX)/libusbvirt.a \
-	$(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += \
-	-I$(LIBUSBVIRT_PREFIX)/include \
-	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBUSBHOST_PREFIX)/include \
-	-I$(LIBUSB_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
-BINARY = vhc
-
-SOURCES = \
-	hub/virthub.c \
-	hub/hub.c \
-	hub/virthubops.c \
-	conndev.c \
-	connhost.c \
-	devconn.c \
-	hub.c \
-	main.c \
-	transfer.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/vhc/conn.h
===================================================================
--- uspace/drv/vhc/conn.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,54 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief Connection handling of incoming calls.
- */
-#ifndef VHCD_CONN_H_
-#define VHCD_CONN_H_
-
-#include <usb/usb.h>
-#include <usbhc_iface.h>
-#include <usb_iface.h>
-#include "vhcd.h"
-
-extern usbhc_iface_t vhc_iface;
-extern usb_iface_t vhc_usb_iface;
-extern usb_iface_t rh_usb_iface;
-
-void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
-void on_client_close(ddf_fun_t *);
-
-
-#endif
-/**
- * @}
- */
Index: pace/drv/vhc/conndev.c
===================================================================
--- uspace/drv/vhc/conndev.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,139 +1,0 @@
-/*
- * 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 drvusbvhc
- * @{
- */
-/** @file
- * Connection handling of calls from virtual device (implementation).
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <ddf/driver.h>
-#include <usbvirt/ipc.h>
-#include <async.h>
-#include "conn.h"
-
-static fibril_local uintptr_t plugged_device_handle = 0;
-#define PLUGGED_DEVICE_NAME_MAXLEN 256
-static fibril_local char plugged_device_name[PLUGGED_DEVICE_NAME_MAXLEN + 1] = "<unknown>";
-
-/** Receive device name.
- *
- * @warning Errors are silently ignored.
- *
- * @param sess Session to the virtual device.
- *
- */
-static void receive_device_name(async_sess_t *sess)
-{
-	async_exch_t *exch = async_exchange_begin(sess);
-	
-	aid_t opening_request = async_send_0(exch, IPC_M_USBVIRT_GET_NAME, NULL);
-	if (opening_request == 0) {
-		async_exchange_end(exch);
-		return;
-	}
-	
-	ipc_call_t data_request_call;
-	aid_t data_request = async_data_read(exch, plugged_device_name,
-	     PLUGGED_DEVICE_NAME_MAXLEN, &data_request_call);
-	
-	async_exchange_end(exch);
-	
-	if (data_request == 0) {
-		async_wait_for(opening_request, NULL);
-		return;
-	}
-	
-	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) || (opening_request_rc != EOK))
-		return;
-	
-	size_t len = IPC_GET_ARG2(data_request_call);
-	plugged_device_name[len] = 0;
-}
-
-/** Default handler for IPC methods not handled by DDF.
- *
- * @param fun Device handling the call.
- * @param icallid Call id.
- * @param icall Call data.
- */
-void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid,
-    ipc_call_t *icall)
-{
-	vhc_data_t *vhc = fun->dev->driver_data;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
-	
-	if (callback) {
-		int rc = vhc_virtdev_plug(vhc, callback, &plugged_device_handle);
-		if (rc != EOK) {
-			async_answer_0(icallid, rc);
-			async_hangup(callback);
-			return;
-		}
-		
-		async_answer_0(icallid, EOK);
-		
-		receive_device_name(callback);
-		
-		usb_log_info("New virtual device `%s' (id: %" PRIxn ").\n",
-		    plugged_device_name, plugged_device_handle);
-	} else
-		async_answer_0(icallid, EINVAL);
-}
-
-/** Callback when client disconnects.
- *
- * Used to unplug virtual USB device.
- *
- * @param fun
- */
-void on_client_close(ddf_fun_t *fun)
-{
-	vhc_data_t *vhc = fun->dev->driver_data;
-
-	if (plugged_device_handle != 0) {
-		usb_log_info("Virtual device `%s' disconnected (id: %" PRIxn ").\n",
-		    plugged_device_name, plugged_device_handle);
-		vhc_virtdev_unplug(vhc, plugged_device_handle);
-	}
-}
-
-
-/**
- * @}
- */
Index: pace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,490 +1,0 @@
-/*
- * 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 drvusbvhc
- * @{
- */
-/** @file
- * Host controller interface implementation.
- */
-#include <assert.h>
-#include <errno.h>
-#include <usb/usb.h>
-#include <usb/ddfiface.h>
-#include <usb/debug.h>
-#include <usbhc_iface.h>
-#include "vhcd.h"
-
-#define GET_VHC_DATA(fun) \
-	((vhc_data_t *)fun->dev->driver_data)
-#define VHC_DATA(vhc, fun) \
-	vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef)
-
-#define UNSUPPORTED(methodname) \
-	usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
-	    methodname, __FILE__, __LINE__)
-
-/** Found free USB address.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] speed Speed of the device that will get this address.
- * @param[out] address Non-null pointer where to store the free address.
- * @return Error code.
- */
-static int request_address(ddf_fun_t *fun, usb_speed_t speed,
-    usb_address_t *address)
-{
-	VHC_DATA(vhc, fun);
-
-	usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper,
-	    USB_SPEED_HIGH);
-	if (addr < 0) {
-		return addr;
-	}
-
-	if (address != NULL) {
-		*address = addr;
-	}
-
-	return EOK;
-}
-
-/** Bind USB address with device devman handle.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address of the device.
- * @param[in] handle Devman handle of the device.
- * @return Error code.
- */
-static int bind_address(ddf_fun_t *fun,
-    usb_address_t address, devman_handle_t handle)
-{
-	VHC_DATA(vhc, fun);
-	usb_log_debug("Binding handle %" PRIun " to address %d.\n",
-	    handle, address);
-	usb_device_keeper_bind(&vhc->dev_keeper, address, handle);
-
-	return EOK;
-}
-
-/** Find device handle by address interface function.
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address Address in question.
- * @param[out] handle Where to store device handle if found.
- * @return Error code.
- */
-static int find_by_address(ddf_fun_t *fun, usb_address_t address,
-    devman_handle_t *handle)
-{
-	VHC_DATA(vhc, fun);
-	bool found =
-	    usb_device_keeper_find_by_address(&vhc->dev_keeper, address, handle);
-	return found ? EOK : ENOENT;
-}
-
-/** Release previously requested address.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address to be released.
- * @return Error code.
- */
-static int release_address(ddf_fun_t *fun, usb_address_t address)
-{
-	VHC_DATA(vhc, fun);
-	usb_log_debug("Releasing address %d...\n", address);
-	usb_device_keeper_release(&vhc->dev_keeper, address);
-
-	return ENOTSUP;
-}
-
-/** Register endpoint for bandwidth reservation.
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address of the device.
- * @param[in] speed Endpoint speed (invalid means to use device one).
- * @param[in] endpoint Endpoint number.
- * @param[in] transfer_type USB transfer type.
- * @param[in] direction Endpoint data direction.
- * @param[in] max_packet_size Max packet size of the endpoint.
- * @param[in] interval Polling interval.
- * @return Error code.
- */
-static int register_endpoint(ddf_fun_t *fun,
-    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
-    usb_transfer_type_t transfer_type, usb_direction_t direction,
-    size_t max_packet_size, unsigned int interval)
-{
-	VHC_DATA(vhc, fun);
-
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
-	if (ep == NULL) {
-		return ENOMEM;
-	}
-
-	int rc = endpoint_init(ep, address, endpoint, direction, transfer_type,
-	    USB_SPEED_FULL, 1);
-	if (rc != EOK) {
-		free(ep);
-		return rc;
-	}
-
-	rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
-	if (rc != EOK) {
-		endpoint_destroy(ep);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Unregister endpoint (free some bandwidth reservation).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] address USB address of the device.
- * @param[in] endpoint Endpoint number.
- * @param[in] direction Endpoint data direction.
- * @return Error code.
- */
-static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction)
-{
-	VHC_DATA(vhc, fun);
-
-	endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
-	    address, endpoint, direction, NULL);
-	if (ep == NULL) {
-		return ENOENT;
-	}
-
-	int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
-	    address, endpoint, direction);
-
-	return rc;
-}
-
-/** Schedule interrupt out transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
- *	by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	VHC_DATA(vhc, fun);
-
-	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
-	    target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_INTERRUPT,
-	    fun, arg);
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->data_buffer = data;
-	transfer->data_buffer_size = size;
-	transfer->callback_out = callback;
-
-	int rc = vhc_virtdev_add_transfer(vhc, transfer);
-	if (rc != EOK) {
-		free(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Schedule interrupt in transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	VHC_DATA(vhc, fun);
-
-	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
-	    target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_INTERRUPT,
-	    fun, arg);
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->data_buffer = data;
-	transfer->data_buffer_size = size;
-	transfer->callback_in = callback;
-
-	int rc = vhc_virtdev_add_transfer(vhc, transfer);
-	if (rc != EOK) {
-		free(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Schedule bulk out transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
- *	by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int bulk_out(ddf_fun_t *fun, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	UNSUPPORTED("bulk_out");
-
-	return ENOTSUP;
-}
-
-/** Schedule bulk in transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] data Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] size Size of the @p data buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int bulk_in(ddf_fun_t *fun, usb_target_t target,
-    void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	UNSUPPORTED("bulk_in");
-
-	return ENOTSUP;
-}
-
-/** Schedule control write transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
- *	and deallocated by the caller).
- * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
- * @param[in] data_buffer Data buffer (in USB endianess, allocated and
- *	deallocated by the caller).
- * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int control_write(ddf_fun_t *fun, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *data_buffer, size_t data_buffer_size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	VHC_DATA(vhc, fun);
-
-	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
-	    target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_CONTROL,
-	    fun, arg);
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->setup_buffer = setup_packet;
-	transfer->setup_buffer_size = setup_packet_size;
-	transfer->data_buffer = data_buffer;
-	transfer->data_buffer_size = data_buffer_size;
-	transfer->callback_out = callback;
-
-	int rc = vhc_virtdev_add_transfer(vhc, transfer);
-	if (rc != EOK) {
-		free(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Schedule control read transfer.
- *
- * The callback is supposed to be called once the transfer (on the wire) is
- * complete regardless of the outcome.
- * However, the callback could be called only when this function returns
- * with success status (i.e. returns EOK).
- *
- * @param[in] fun Device function the action was invoked on.
- * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
- *	and deallocated by the caller).
- * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
- * @param[in] data_buffer Buffer where to store the data (in USB endianess,
- *	allocated and deallocated by the caller).
- * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
- * @param[in] callback Callback to be issued once the transfer is complete.
- * @param[in] arg Pass-through argument to the callback.
- * @return Error code.
- */
-static int control_read(ddf_fun_t *fun, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *data_buffer, size_t data_buffer_size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	VHC_DATA(vhc, fun);
-
-	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
-	    target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_CONTROL,
-	    fun, arg);
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->setup_buffer = setup_packet;
-	transfer->setup_buffer_size = setup_packet_size;
-	transfer->data_buffer = data_buffer;
-	transfer->data_buffer_size = data_buffer_size;
-	transfer->callback_in = callback;
-
-	int rc = vhc_virtdev_add_transfer(vhc, transfer);
-	if (rc != EOK) {
-		free(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
-    usb_address_t *address)
-{
-	UNSUPPORTED("tell_address");
-
-	return ENOTSUP;
-}
-
-static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
-    devman_handle_t *handle)
-{
-	VHC_DATA(vhc, root_hub_fun);
-
-	*handle = vhc->hc_fun->handle;
-
-	return EOK;
-}
-
-static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
-    usb_address_t *address)
-{
-	VHC_DATA(vhc, root_hub_fun);
-
-	if (handle == 0) {
-		handle = root_hub_fun->handle;
-	}
-
-	usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
-	usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle);
-	if (addr < 0) {
-		return addr;
-	} else {
-		*address = addr;
-		return EOK;
-	}
-}
-
-usbhc_iface_t vhc_iface = {
-	.request_address = request_address,
-	.bind_address = bind_address,
-	.find_by_address = find_by_address,
-	.release_address = release_address,
-
-	.register_endpoint = register_endpoint,
-	.unregister_endpoint = unregister_endpoint,
-
-	.interrupt_out = interrupt_out,
-	.interrupt_in = interrupt_in,
-
-	.bulk_in = bulk_in,
-	.bulk_out = bulk_out,
-
-	.control_write = control_write,
-	.control_read = control_read
-};
-
-usb_iface_t vhc_usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle_hc_impl,
-	.get_address = tell_address
-};
-
-usb_iface_t rh_usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle_rh_impl,
-	.get_address = tell_address_rh
-};
-
-
-/**
- * @}
- */
Index: pace/drv/vhc/devconn.c
===================================================================
--- uspace/drv/vhc/devconn.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,114 +1,0 @@
-/*
- * 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.
- */
-
-#include <errno.h>
-#include "vhcd.h"
-#include "hub/virthub.h"
-
-
-static vhc_virtdev_t *vhc_virtdev_create()
-{
-	vhc_virtdev_t *dev = malloc(sizeof(vhc_virtdev_t));
-	if (dev == NULL) {
-		return NULL;
-	}
-	dev->address = 0;
-	dev->dev_sess = NULL;
-	dev->dev_local = NULL;
-	dev->plugged = true;
-	link_initialize(&dev->link);
-	fibril_mutex_initialize(&dev->guard);
-	list_initialize(&dev->transfer_queue);
-
-	return dev;
-}
-
-static int vhc_virtdev_plug_generic(vhc_data_t *vhc,
-    async_sess_t *sess, usbvirt_device_t *virtdev,
-    uintptr_t *handle, bool connect)
-{
-	vhc_virtdev_t *dev = vhc_virtdev_create();
-	if (dev == NULL) {
-		return ENOMEM;
-	}
-
-	dev->dev_sess = sess;
-	dev->dev_local = virtdev;
-
-	fibril_mutex_lock(&vhc->guard);
-	list_append(&dev->link, &vhc->devices);
-	fibril_mutex_unlock(&vhc->guard);
-
-	fid_t fibril = fibril_create(vhc_transfer_queue_processor, dev);
-	if (fibril == 0) {
-		free(dev);
-		return ENOMEM;
-	}
-	fibril_add_ready(fibril);
-
-	if (handle != NULL) {
-		*handle = (uintptr_t) dev;
-	}
-
-	if (connect) {
-		// FIXME: check status
-		(void) virthub_connect_device(vhc->hub, dev);
-	}
-
-	return EOK;
-}
-
-int vhc_virtdev_plug(vhc_data_t *vhc, async_sess_t *sess, uintptr_t *handle)
-{
-	return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true);
-}
-
-int vhc_virtdev_plug_local(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
-{
-	return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true);
-}
-
-int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
-{
-	return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false);
-}
-
-void vhc_virtdev_unplug(vhc_data_t *vhc, uintptr_t handle)
-{
-	vhc_virtdev_t *dev = (vhc_virtdev_t *) handle;
-
-	// FIXME: check status
-	(void) virthub_disconnect_device(vhc->hub, dev);
-
-	fibril_mutex_lock(&vhc->guard);
-	fibril_mutex_lock(&dev->guard);
-	dev->plugged = false;
-	list_remove(&dev->link);
-	fibril_mutex_unlock(&dev->guard);
-	fibril_mutex_unlock(&vhc->guard);
-}
Index: pace/drv/vhc/hub.c
===================================================================
--- uspace/drv/vhc/hub.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,135 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief Virtual USB hub.
- */
-
-#include <usb/classes/classes.h>
-#include <usbvirt/device.h>
-#include <errno.h>
-#include <async.h>
-#include <str_error.h>
-#include <stdlib.h>
-#include <ddf/driver.h>
-#include <devman.h>
-#include <usb/dev/hub.h>
-#include <usb/dev/recognise.h>
-
-#include "hub.h"
-#include "vhcd.h"
-#include "conn.h"
-
-usbvirt_device_t virtual_hub_device = {
-	.name = "root hub",
-	.ops = &hub_ops,
-	.address = 0
-};
-
-static ddf_dev_ops_t rh_ops = {
-	.interfaces[USB_DEV_IFACE] = &rh_usb_iface,
-};
-
-static int hub_register_in_devman_fibril(void *arg);
-
-void virtual_hub_device_init(ddf_fun_t *hc_dev)
-{
-	virthub_init(&virtual_hub_device);
-
-	/*
-	 * We need to register the root hub.
-	 * This must be done in separate fibril because the device
-	 * we are connecting to are ourselves and we cannot connect
-	 * before leaving the add_device() function.
-	 */
-	fid_t root_hub_registration
-	    = fibril_create(hub_register_in_devman_fibril, hc_dev);
-	if (root_hub_registration == 0) {
-		usb_log_fatal("Failed to create hub registration fibril.\n");
-		return;
-	}
-
-	fibril_add_ready(root_hub_registration);
-}
-
-static int pretend_port_rest(int unused, void *unused2)
-{
-	return EOK;
-}
-
-/** Register root hub in devman.
- *
- * @param arg Host controller device (type <code>device_t *</code>).
- * @return Error code.
- */
-int hub_register_in_devman_fibril(void *arg)
-{
-	ddf_fun_t *hc_dev = (ddf_fun_t *) arg;
-
-	/*
-	 * Wait until parent device is properly initialized.
-	 */
-	async_sess_t *sess;
-	do {
-		sess = devman_device_connect(EXCHANGE_SERIALIZE, hc_dev->handle, 0);
-	} while (!sess);
-	async_hangup(sess);
-
-	int rc;
-
-	usb_hc_connection_t hc_conn;
-	rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
-	assert(rc == EOK);
-
-	rc = usb_hc_connection_open(&hc_conn);
-	assert(rc == EOK);
-
-	ddf_fun_t *hub_dev;
-	rc = usb_hc_new_device_wrapper(hc_dev->dev, &hc_conn,
-	    USB_SPEED_FULL,
-	    pretend_port_rest, 0, NULL,
-	    NULL, NULL, &rh_ops, hc_dev, &hub_dev);
-	if (rc != EOK) {
-		usb_log_fatal("Failed to create root hub: %s.\n",
-		    str_error(rc));
-	}
-
-	usb_hc_connection_close(&hc_conn);
-
-	usb_log_info("Created root hub function (handle %zu).\n",
-	    (size_t) hub_dev->handle);
-
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/drv/vhc/hub.h
===================================================================
--- uspace/drv/vhc/hub.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,52 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief Virtual USB hub.
- */
-
-#ifndef VHCD_HUB_H_
-#define VHCD_HUB_H_
-
-#include <usbvirt/device.h>
-#include <ddf/driver.h>
-
-#include "hub/hub.h"
-#include "hub/virthub.h"
-
-extern usbvirt_device_t virtual_hub_device;
-
-void virtual_hub_device_init(ddf_fun_t *);
-
-#endif
-/**
- * @}
- */
Index: pace/drv/vhc/hub/hub.c
===================================================================
--- uspace/drv/vhc/hub/hub.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,523 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief Representation of an USB hub (implementation).
- */
-#include <usb/classes/classes.h>
-#include <usbvirt/device.h>
-#include <errno.h>
-#include <str_error.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <ddf/driver.h>
-#include <usb/debug.h>
-
-#include "hub.h"
-
-
-/** Produce a byte from bit values.
- */
-#define MAKE_BYTE(b0, b1, b2, b3, b4, b5, b6, b7) \
-	(( \
-		((b0) << 0) \
-		| ((b1) << 1) \
-		| ((b2) << 2) \
-		| ((b3) << 3) \
-		| ((b4) << 4) \
-		| ((b5) << 5) \
-		| ((b6) << 6) \
-		| ((b7) << 7) \
-	))
-
-/* Static functions. */
-static hub_port_t *get_hub_port(hub_t *, size_t);
-static void set_port_status_change(hub_port_t *, hub_status_change_t);
-static void clear_port_status_change(hub_port_t *, uint16_t);
-static int set_port_state_delayed_fibril(void *);
-static void set_port_state_delayed(hub_t *, size_t, suseconds_t,
-    hub_port_state_t, hub_port_state_t);
-
-/** Convert hub port state to a char. */
-char hub_port_state_to_char(hub_port_state_t state) {
-	switch (state) {
-		case HUB_PORT_STATE_NOT_CONFIGURED:
-			return '-';
-		case HUB_PORT_STATE_POWERED_OFF:
-			return 'O';
-		case HUB_PORT_STATE_DISCONNECTED:
-			return 'X';
-		case HUB_PORT_STATE_DISABLED:
-			return 'D';
-		case HUB_PORT_STATE_RESETTING:
-			return 'R';
-		case HUB_PORT_STATE_ENABLED:
-			return 'E';
-		case HUB_PORT_STATE_SUSPENDED:
-			return 'S';
-		case HUB_PORT_STATE_RESUMING:
-			return 'F';
-		default:
-			return '?';
-	}
-}
-
-/** Initialize single hub port.
- *
- * @param port Port to be initialized.
- * @param index Port index (one based).
- */
-static void hub_init_port(hub_port_t *port, hub_t *hub, size_t index)
-{
-	port->connected_device = NULL;
-	port->index = index;
-	port->state = HUB_PORT_STATE_NOT_CONFIGURED;
-	port->status_change = 0;
-	port->hub = hub;
-}
-
-/** Initialize the hub.
- *
- * @param hub Hub to be initialized.
- */
-void hub_init(hub_t *hub)
-{
-	size_t i;
-	for (i = 0; i < HUB_PORT_COUNT; i++) {
-		hub_init_port(&hub->ports[i], hub, i + 1);
-	}
-	hub->custom_data = NULL;
-	hub->signal_changes = true;
-	fibril_mutex_initialize(&hub->guard);
-}
-
-/** Connect a device to the hub.
- *
- * @param hub Hub to connect device to.
- * @param device Device to be connected.
- * @return Index of port the device was connected to.
- * @retval -1 No free port available.
- */
-size_t hub_connect_device(hub_t *hub, void *device)
-{
-	size_t i;
-	for (i = 0; i < HUB_PORT_COUNT; i++) {
-		hub_port_t *port = &hub->ports[i];
-
-		if (port->connected_device != NULL) {
-			continue;
-		}
-
-		port->connected_device = device;
-
-		/*
-		 * TODO:
-		 * If the hub was configured, we can normally
-		 * announce the plug-in.
-		 * Otherwise, we will wait until hub is configured
-		 * and announce changes in single burst.
-		 */
-		//if (port->state == HUB_PORT_STATE_DISCONNECTED) {
-			port->state = HUB_PORT_STATE_DISABLED;
-			set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
-		//}
-
-		return i;
-	}
-
-	return (size_t) -1;
-}
-
-/** Disconnects a device from a hub.
- *
- * @param hub Hub the device was connected to.
- * @param device Device to be disconnected.
- * @return Error code.
- */
-int hub_disconnect_device(hub_t *hub, void *device)
-{
-	size_t index = hub_find_device(hub, device);
-	if (index == (size_t) -1) {
-		return ENOENT;
-	}
-
-	hub_port_t *port = &hub->ports[index];
-
-	port->connected_device = NULL;
-	port->state = HUB_PORT_STATE_DISCONNECTED;
-	set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
-
-	return EOK;
-}
-
-/** Find port device is connected to.
- *
- * @param hub Hub in question.
- * @param device Device in question.
- * @return Port index (zero based).
- * @retval -1 Device is not connected.
- */
-size_t hub_find_device(hub_t *hub, void *device)
-{
-	size_t i;
-	for (i = 0; i < HUB_PORT_COUNT; i++) {
-		hub_port_t *port = &hub->ports[i];
-
-		if (port->connected_device == device) {
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-/** Acquire exclusive access to the hub.
- *
- * @param hub Hub in question.
- */
-void hub_acquire(hub_t *hub)
-{
-	fibril_mutex_lock(&hub->guard);
-}
-
-/** Give up exclusive access to the hub.
- *
- * @param hub Hub in question.
- */
-void hub_release(hub_t *hub)
-{
-	fibril_mutex_unlock(&hub->guard);
-}
-
-/** Change port state.
- *
- * @param hub Hub the port belongs to.
- * @param port_index Port index (zero based).
- * @param state New port state.
- */
-void hub_set_port_state(hub_t *hub, size_t port_index, hub_port_state_t state)
-{
-	hub_port_t *port = get_hub_port(hub, port_index);
-	if (port == NULL) {
-		return;
-	}
-
-	usb_log_debug("Setting port %zu to state %d.\n", port_index, state);
-
-	switch (state) {
-		case HUB_PORT_STATE_POWERED_OFF:
-			clear_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
-			clear_port_status_change(port, HUB_STATUS_C_PORT_ENABLE);
-			clear_port_status_change(port, HUB_STATUS_C_PORT_RESET);
-			break;
-		case HUB_PORT_STATE_RESUMING:
-			port->state = state;
-			set_port_state_delayed(hub, port_index,
-			    10, state, HUB_PORT_STATE_ENABLED);
-			break;
-		case HUB_PORT_STATE_RESETTING:
-			port->state = state;
-			set_port_state_delayed(hub, port_index,
-			    10, state, HUB_PORT_STATE_ENABLED);
-			break;
-		case HUB_PORT_STATE_ENABLED:
-			if (port->state == HUB_PORT_STATE_RESETTING) {
-				set_port_status_change(port, HUB_STATUS_C_PORT_RESET);
-			}
-			break;
-		default:
-			break;
-	}
-
-	port->state = state;
-}
-
-/** Change state of all ports.
- *
- * @param hub Hub in question.
- * @param state New state for all ports.
- */
-void hub_set_port_state_all(hub_t *hub, hub_port_state_t state)
-{
-	size_t i;
-	for (i = 0; i < HUB_PORT_COUNT; i++) {
-		hub_set_port_state(hub, i, state);
-	}
-}
-
-/** Get port state.
- *
- * @param hub Hub the port belongs to.
- * @param port_index Port index (zero based).
- * @return Port state.
- */
-hub_port_state_t hub_get_port_state(hub_t *hub, size_t port_index)
-{
-	hub_port_t *port = get_hub_port(hub, port_index);
-	if (port == NULL) {
-		return HUB_PORT_STATE_UNKNOWN;
-	}
-
-	return port->state;
-}
-
-/** Clear port status change bit.
- *
- * @param hub Hub the port belongs to.
- * @param port_index Port index (zero based).
- * @param change Change to be cleared.
- */
-void hub_clear_port_status_change(hub_t *hub, size_t port_index,
-    hub_status_change_t change)
-{
-	hub_port_t *port = get_hub_port(hub, port_index);
-	if (port == NULL) {
-		return;
-	}
-
-	clear_port_status_change(port, change);
-}
-
-/** Get port status change bits.
- *
- * @param hub Hub the port belongs to.
- * @param port_index Port index (zero based).
- * @return Port status change bitmap in standard format.
- */
-uint16_t hub_get_port_status_change(hub_t *hub, size_t port_index)
-{
-	hub_port_t *port = get_hub_port(hub, port_index);
-	if (port == NULL) {
-		return 0;
-	}
-
-	return port->status_change;
-}
-
-/** Get port status bits.
- *
- * @param hub Hub the port belongs to.
- * @param port_index Port index (zero based).
- * @return Port status bitmap in standard format.
- */
-uint32_t hub_get_port_status(hub_t *hub, size_t port_index)
-{
-	hub_port_t *port = get_hub_port(hub, port_index);
-	if (port == NULL) {
-		return 0;
-	}
-
-	uint32_t status;
-	status = MAKE_BYTE(
-	    /* Current connect status. */
-	    port->connected_device == NULL ? 0 : 1,
-	    /* Port enabled/disabled. */
-	    port->state == HUB_PORT_STATE_ENABLED ? 1 : 0,
-	    /* Suspend. */
-	    (port->state == HUB_PORT_STATE_SUSPENDED)
-		|| (port->state == HUB_PORT_STATE_RESUMING) ? 1 : 0,
-	    /* Over-current. */
-	    0,
-	    /* Reset. */
-	    port->state == HUB_PORT_STATE_RESETTING ? 1 : 0,
-	    /* Reserved. */
-	    0, 0, 0)
-
-	    | (MAKE_BYTE(
-	    /* Port power. */
-	    port->state == HUB_PORT_STATE_POWERED_OFF ? 0 : 1,
-	    /* Full-speed device. */
-	    0,
-	    /* Reserved. */
-	    0, 0, 0, 0, 0, 0
-	    )) << 8;
-
-	status |= (port->status_change << 16);
-
-	return status;
-}
-
-/** Create hub status change bitmap.
- *
- * @warning This function assumes that the whole bitmap fits into 8 bits.
- *
- * @param hub Hub in question.
- * @return Hub status change bitmap.
- */
-uint8_t hub_get_status_change_bitmap(hub_t *hub)
-{
-	uint8_t change_map = 0;
-
-	size_t i;
-	for (i = 0; i < HUB_PORT_COUNT; i++) {
-		hub_port_t *port = &hub->ports[i];
-
-		if (port->status_change != 0) {
-			change_map |= (1 << port->index);
-		}
-	}
-
-	return change_map;
-}
-
-
-/*
- *
- * STATIC (HELPER) FUNCTIONS
- *
- */
-
-/** Find a port in a hub.
- *
- * @param hub Hub in question.
- * @param port Port index (zero based).
- * @return Port structure.
- * @retval NULL Invalid port index.
- */
-static hub_port_t *get_hub_port(hub_t *hub, size_t port)
-{
-	if (port >= HUB_PORT_COUNT) {
-		return NULL;
-	}
-
-	return &hub->ports[port];
-}
-
-/** Adds a port status change to a port.
- *
- * @param port The port with status change.
- * @param change Change to be added to the status.
- */
-static void set_port_status_change(hub_port_t *port,
-    hub_status_change_t change)
-{
-	assert(port != NULL);
-	uint16_t old_value = port->status_change;
-	port->status_change |= change;
-	usb_log_debug("Changing status change on %zu: %04x => %04x\n",
-	    port->index,
-	    (unsigned int) old_value, (unsigned int) port->status_change);
-	port->hub->signal_changes = true;
-}
-
-/** Clears a port status change on a port.
- *
- * @param port The port with status change.
- * @param change Change to be removed from the status.
- */
-static void clear_port_status_change(hub_port_t *port,
-    uint16_t change)
-{
-	assert(port != NULL);
-	port->status_change &= (~change);
-	port->hub->signal_changes = true;
-}
-
-/** Structure for automatic (delayed) port state change. */
-struct delay_port_state_change {
-	/** Delay in microseconds. */
-	suseconds_t delay;
-	/** Old state of the port. */
-	hub_port_state_t old_state;
-	/** New state of the port. */
-	hub_port_state_t new_state;
-	/** Port index (zero based). */
-	size_t port;
-	/** Hub. */
-	hub_t *hub;
-};
-
-/** Fibril responsible for delayed port state change.
- *
- * @param arg Pointer to delay_port_state_change.
- * @return Always EOK.
- */
-static int set_port_state_delayed_fibril(void *arg)
-{
-	struct delay_port_state_change *change
-	    = (struct delay_port_state_change *) arg;
-
-	async_usleep(change->delay);
-
-	hub_acquire(change->hub);
-
-	hub_port_t *port = get_hub_port(change->hub, change->port);
-	assert(port != NULL);
-
-	if (port->state == change->old_state) {
-		hub_set_port_state(change->hub, change->port,
-		    change->new_state);
-	}
-
-	hub_release(change->hub);
-
-	free(change);
-
-	return EOK;
-}
-
-/** Change port state with a delay.
- *
- * @warning If the port state changes during the waiting phase, the state
- * is not changed.
- *
- * @param hub Hub in question.
- * @param port_index Port index (zero based).
- * @param delay_time_ms Delay time in miliseconds.
- * @param old_state Old (current) state of the port.
- * @param new_state New state of the port.
- */
-static void set_port_state_delayed(hub_t *hub, size_t port_index,
-    suseconds_t delay_time_ms,
-    hub_port_state_t old_state, hub_port_state_t new_state)
-{
-	struct delay_port_state_change *change
-	    = malloc(sizeof(struct delay_port_state_change));
-
-	change->hub = hub;
-	change->port = port_index;
-	change->delay = delay_time_ms * 1000;
-	change->old_state = old_state;
-	change->new_state = new_state;
-	fid_t fibril = fibril_create(set_port_state_delayed_fibril, change);
-	if (fibril == 0) {
-		printf("Failed to create fibril\n");
-		free(change);
-		return;
-	}
-	fibril_add_ready(fibril);
-}
-
-
-
-/**
- * @}
- */
Index: pace/drv/vhc/hub/hub.h
===================================================================
--- uspace/drv/vhc/hub/hub.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,120 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief Representation of an USB hub.
- */
-#ifndef VHC_HUB_HUB_H_
-#define VHC_HUB_HUB_H_
-
-#include <fibril_synch.h>
-
-#ifndef HUB_PORT_COUNT
-#define HUB_PORT_COUNT 2
-#endif
-#define BITS2BYTES(bits) (bits ? ((((bits)-1)>>3)+1) : 0)
-
-/** Hub port internal state.
- * Some states (e.g. port over current) are not covered as they are not
- * simulated at all.
- */
-typedef enum {
-	HUB_PORT_STATE_UNKNOWN,
-	HUB_PORT_STATE_NOT_CONFIGURED,
-	HUB_PORT_STATE_POWERED_OFF,
-	HUB_PORT_STATE_DISCONNECTED,
-	HUB_PORT_STATE_DISABLED,
-	HUB_PORT_STATE_RESETTING,
-	HUB_PORT_STATE_ENABLED,
-	HUB_PORT_STATE_SUSPENDED,
-	HUB_PORT_STATE_RESUMING,
-	/* HUB_PORT_STATE_, */
-} hub_port_state_t;
-
-char hub_port_state_to_char(hub_port_state_t);
-
-/** Hub status change mask bits. */
-typedef enum {
-	HUB_STATUS_C_PORT_CONNECTION = (1 << 0),
-	HUB_STATUS_C_PORT_ENABLE = (1 << 1),
-	HUB_STATUS_C_PORT_SUSPEND = (1 << 2),
-	HUB_STATUS_C_PORT_OVER_CURRENT = (1 << 3),
-	HUB_STATUS_C_PORT_RESET = (1 << 4),
-	/* HUB_STATUS_C_ = (1 << ), */
-} hub_status_change_t;
-
-typedef struct hub hub_t;
-
-/** Hub port information. */
-typedef struct {
-	/** Custom pointer to connected device. */
-	void *connected_device;
-	/** Port index (one based). */
-	size_t index;
-	/** Port state. */
-	hub_port_state_t state;
-	/** Status change bitmap. */
-	uint16_t status_change;
-	/** Containing hub. */
-	hub_t *hub;
-} hub_port_t;
-
-/** Hub device type. */
-struct hub {
-	/** Hub ports. */
-	hub_port_t ports[HUB_PORT_COUNT];
-	/** Custom hub data. */
-	void *custom_data;
-	/** Access guard to the whole hub. */
-	fibril_mutex_t guard;
-	/** Last value of status change bitmap. */
-	bool signal_changes;
-};
-
-void hub_init(hub_t *);
-size_t hub_connect_device(hub_t *, void *);
-int hub_disconnect_device(hub_t *, void *);
-size_t hub_find_device(hub_t *, void *);
-void hub_acquire(hub_t *);
-void hub_release(hub_t *);
-void hub_set_port_state(hub_t *, size_t, hub_port_state_t);
-void hub_set_port_state_all(hub_t *, hub_port_state_t);
-hub_port_state_t hub_get_port_state(hub_t *, size_t);
-void hub_clear_port_status_change(hub_t *, size_t, hub_status_change_t);
-uint16_t hub_get_port_status_change(hub_t *, size_t);
-uint32_t hub_get_port_status(hub_t *, size_t);
-uint8_t hub_get_status_change_bitmap(hub_t *);
-
-
-#endif
-/**
- * @}
- */
Index: pace/drv/vhc/hub/virthub.c
===================================================================
--- uspace/drv/vhc/hub/virthub.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,260 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief
- */
-#include <usb/classes/classes.h>
-#include <usbvirt/device.h>
-#include <assert.h>
-#include <errno.h>
-#include <str_error.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <ddf/driver.h>
-
-#include "virthub.h"
-#include "hub.h"
-
-
-/** Standard device descriptor. */
-usb_standard_device_descriptor_t std_device_descriptor = {
-	.length = sizeof(usb_standard_device_descriptor_t),
-	.descriptor_type = USB_DESCTYPE_DEVICE,
-	.usb_spec_version = 0x110,
-	.device_class = USB_CLASS_HUB,
-	.device_subclass = 0,
-	.device_protocol = 0,
-	.max_packet_size = 64,
-	.configuration_count = 1
-};
-
-/** Standard interface descriptor. */
-usb_standard_interface_descriptor_t std_interface_descriptor = {
-	.length = sizeof(usb_standard_interface_descriptor_t),
-	.descriptor_type = USB_DESCTYPE_INTERFACE,
-	.interface_number = 0,
-	.alternate_setting = 0,
-	.endpoint_count = 1,
-	.interface_class = USB_CLASS_HUB,
-	.interface_subclass = 0,
-	.interface_protocol = 0,
-	.str_interface = 0
-};
-
-/** Hub descriptor. */
-hub_descriptor_t hub_descriptor = {
-	.length = sizeof(hub_descriptor_t),
-	.type = USB_DESCTYPE_HUB,
-	.port_count = HUB_PORT_COUNT,
-	.characteristics = 0, 
-	.power_on_warm_up = 50, /* Huh? */
-	.max_current = 100, /* Huh again. */
-	.removable_device = { 0 },
-	.port_power = { 0xFF }
-};
-
-/** Endpoint descriptor. */
-usb_standard_endpoint_descriptor_t endpoint_descriptor = {
-	.length = sizeof(usb_standard_endpoint_descriptor_t),
-	.descriptor_type = USB_DESCTYPE_ENDPOINT,
-	.endpoint_address = HUB_STATUS_CHANGE_PIPE | 128,
-	.attributes = USB_TRANSFER_INTERRUPT,
-	.max_packet_size = 8,
-	.poll_interval = 0xFF
-};
-
-/** Standard configuration descriptor. */
-usb_standard_configuration_descriptor_t std_configuration_descriptor = {
-	.length = sizeof(usb_standard_configuration_descriptor_t),
-	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
-	.total_length = 
-		sizeof(usb_standard_configuration_descriptor_t)
-		+ sizeof(std_interface_descriptor)
-		+ sizeof(hub_descriptor)
-		+ sizeof(endpoint_descriptor)
-		,
-	.interface_count = 1,
-	.configuration_number = HUB_CONFIGURATION_ID,
-	.str_configuration = 0,
-	.attributes = 128, /* denotes bus-powered device */
-	.max_power = 50
-};
-
-/** All hub configuration descriptors. */
-static usbvirt_device_configuration_extras_t extra_descriptors[] = {
-	{
-		.data = (uint8_t *) &std_interface_descriptor,
-		.length = sizeof(std_interface_descriptor)
-	},
-	{
-		.data = (uint8_t *) &hub_descriptor,
-		.length = sizeof(hub_descriptor)
-	},
-	{
-		.data = (uint8_t *) &endpoint_descriptor,
-		.length = sizeof(endpoint_descriptor)
-	}
-};
-
-/** Hub configuration. */
-usbvirt_device_configuration_t configuration = {
-	.descriptor = &std_configuration_descriptor,
-	.extra = extra_descriptors,
-	.extra_count = sizeof(extra_descriptors)/sizeof(extra_descriptors[0])
-};
-
-/** Hub standard descriptors. */
-usbvirt_descriptors_t descriptors = {
-	.device = &std_device_descriptor,
-	.configuration = &configuration,
-	.configuration_count = 1,
-};
-
-/** Initializes virtual hub device.
- *
- * @param dev Virtual USB device backend.
- * @return Error code.
- */
-int virthub_init(usbvirt_device_t *dev)
-{
-	if (dev == NULL) {
-		return EBADMEM;
-	}
-	dev->ops = &hub_ops;
-	dev->descriptors = &descriptors;
-
-	hub_t *hub = malloc(sizeof(hub_t));
-	if (hub == NULL) {
-		return ENOMEM;
-	}
-
-	hub_init(hub);
-	dev->device_data = hub;
-
-	return EOK;
-}
-
-/** Connect a device to a virtual hub.
- *
- * @param dev Virtual device representing the hub.
- * @param conn Device to be connected.
- * @return Port device was connected to.
- */
-int virthub_connect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
-{
-	assert(dev != NULL);
-	assert(conn != NULL);
-
-	hub_t *hub = (hub_t *) dev->device_data;
-
-	hub_acquire(hub);
-	size_t port = hub_connect_device(hub, conn);
-	hub_release(hub);
-
-	return port;
-}
-
-/** Disconnect a device from a virtual hub.
- *
- * @param dev Virtual device representing the hub.
- * @param conn Device to be disconnected.
- * @return Error code.
- */
-int virthub_disconnect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
-{
-	assert(dev != NULL);
-	assert(conn != NULL);
-
-	hub_t *hub = (hub_t *) dev->device_data;
-
-	hub_acquire(hub);
-	hub_disconnect_device(hub, conn);
-	hub_release(hub);
-
-	return EOK;
-}
-
-/** Whether trafic is propagated to given device.
- *
- * @param dev Virtual device representing the hub.
- * @param conn Connected device.
- * @return Whether port is signalling to the device.
- */
-bool virthub_is_device_enabled(usbvirt_device_t *dev, vhc_virtdev_t *conn)
-{
-	assert(dev != NULL);
-	assert(conn != NULL);
-
-	hub_t *hub = (hub_t *) dev->device_data;
-
-	hub_acquire(hub);
-
-	hub_port_state_t state = HUB_PORT_STATE_UNKNOWN;
-	size_t port = hub_find_device(hub, conn);
-	if (port != (size_t) -1) {
-		state = hub_get_port_state(hub, port);
-	}
-	hub_release(hub);
-
-	return state == HUB_PORT_STATE_ENABLED;
-}
-
-/** Format status of a virtual hub.
- *
- * @param dev Virtual device representing the hub.
- * @param[out] status Hub status information.
- * @param[in] len Size of the @p status buffer.
- */
-void virthub_get_status(usbvirt_device_t *dev, char *status, size_t len)
-{
-	assert(dev != NULL);
-	if (len == 0) {
-		return;
-	}
-
-	hub_t *hub = (hub_t *) dev->device_data;
-
-	char port_status[HUB_PORT_COUNT + 1];
-
-	size_t i;
-	for (i = 0; i < HUB_PORT_COUNT; i++) {
-		port_status[i] = hub_port_state_to_char(
-		    hub_get_port_state(hub, i));
-	}
-	port_status[HUB_PORT_COUNT] = 0;
-
-	snprintf(status, len, "vhub:%s", port_status);
-}
-
-/**
- * @}
- */
Index: pace/drv/vhc/hub/virthub.h
===================================================================
--- uspace/drv/vhc/hub/virthub.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,90 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief USB hub as a virtual USB device.
- */
-#ifndef VHC_HUB_VIRTHUB_H_
-#define VHC_HUB_VIRTHUB_H_
-
-#include <usbvirt/device.h>
-#include "hub.h"
-
-#ifdef STANDALONE_HUB
-#define virtdev_connection_t int
-#else
-#include "../vhcd.h"
-#endif
-
-/** Endpoint number for status change pipe. */
-#define HUB_STATUS_CHANGE_PIPE 1
-/** Configuration value for hub configuration. */
-#define HUB_CONFIGURATION_ID 1
-
-
-/** Hub descriptor.
- */
-typedef struct {
-	/** Size of this descriptor in bytes. */
-	uint8_t length;
-	/** Descriptor type (USB_DESCTYPE_HUB). */
-	uint8_t type;
-	/** Number of downstream ports. */
-	uint8_t port_count;
-	/** Hub characteristics. */
-	uint16_t characteristics;
-	/** Time from power-on to stabilized current.
-	 * Expressed in 2ms unit.
-	 */
-	uint8_t power_on_warm_up;
-	/** Maximum current (in mA). */
-	uint8_t max_current;
-	/** Whether device at given port is removable. */
-	uint8_t removable_device[BITS2BYTES(HUB_PORT_COUNT+1)];
-	/** Port power control.
-	 * This is USB1.0 compatibility field, all bits must be 1.
-	 */
-	uint8_t port_power[BITS2BYTES(HUB_PORT_COUNT+1)];
-} __attribute__ ((packed)) hub_descriptor_t;
-
-extern usbvirt_device_ops_t hub_ops;
-extern hub_descriptor_t hub_descriptor;
-
-int virthub_init(usbvirt_device_t *);
-int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *);
-int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *);
-bool virthub_is_device_enabled(usbvirt_device_t *, vhc_virtdev_t *);
-void virthub_get_status(usbvirt_device_t *, char *, size_t);
-
-#endif
-/**
- * @}
- */
Index: pace/drv/vhc/hub/virthubops.c
===================================================================
--- uspace/drv/vhc/hub/virthubops.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,457 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief Virtual USB hub operations.
- */
-#include <errno.h>
-#include <usb/classes/hub.h>
-#include <usbvirt/device.h>
-#include "virthub.h"
-#include "hub.h"
-
-/** Callback when device changes states. */
-static void on_state_change(usbvirt_device_t *dev,
-    usbvirt_device_state_t old_state, usbvirt_device_state_t new_state)
-{
-	hub_t *hub = (hub_t *)dev->device_data;
-
-	hub_acquire(hub);
-
-	switch (new_state) {
-		case USBVIRT_STATE_CONFIGURED:
-			hub_set_port_state_all(hub, HUB_PORT_STATE_POWERED_OFF);
-			break;
-		case USBVIRT_STATE_ADDRESS:
-			hub_set_port_state_all(hub, HUB_PORT_STATE_NOT_CONFIGURED);
-			break;
-		default:
-			break;
-	}
-
-	hub_release(hub);
-}
-
-/** Callback for data request. */
-static int req_on_status_change_pipe(usbvirt_device_t *dev,
-    usb_endpoint_t endpoint, usb_transfer_type_t tr_type,
-    void *buffer, size_t buffer_size, size_t *actual_size)
-{
-	if (endpoint != HUB_STATUS_CHANGE_PIPE) {
-		return ESTALL;
-	}
-	if (tr_type != USB_TRANSFER_INTERRUPT) {
-		return ESTALL;
-	}
-	
-	hub_t *hub = dev->device_data;
-
-	hub_acquire(hub);
-
-	if (!hub->signal_changes) {
-		hub_release(hub);
-
-		return ENAK;
-	}
-
-
-	uint8_t change_map = hub_get_status_change_bitmap(hub);
-
-	uint8_t *b = (uint8_t *) buffer;
-	if (buffer_size > 0) {
-		*b = change_map;
-		*actual_size = 1;
-	} else {
-		*actual_size = 0;
-	}
-	
-	hub->signal_changes = false;
-
-	hub_release(hub);
-
-	return EOK;
-}
-
-/** Handle ClearHubFeature request.
- *
- * @param dev Virtual device representing the hub.
- * @param request The SETUP packet of the control request.
- * @param data Extra data (when DATA stage present).
- * @return Error code.
- */
-static int req_clear_hub_feature(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *request, uint8_t *data,
-    size_t *act_size)
-{
-	return ENOTSUP;
-}
-
-/** Handle ClearPortFeature request.
- *
- * @param dev Virtual device representing the hub.
- * @param request The SETUP packet of the control request.
- * @param data Extra data (when DATA stage present).
- * @return Error code.
- */
-static int req_clear_port_feature(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *request, uint8_t *data,
-    size_t *act_size)
-{
-	int rc;
-	size_t port = request->index - 1;
-	usb_hub_class_feature_t feature = request->value;
-	hub_t *hub = (hub_t *) dev->device_data;
-
-	hub_acquire(hub);
-
-	hub_port_state_t port_state = hub_get_port_state(hub, port);
-
-	switch (feature) {
-		case USB_HUB_FEATURE_PORT_ENABLE:
-			if ((port_state != HUB_PORT_STATE_NOT_CONFIGURED)
-			    && (port_state != HUB_PORT_STATE_POWERED_OFF)) {
-				hub_set_port_state(hub, port, HUB_PORT_STATE_DISABLED);
-			}
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_PORT_SUSPEND:
-			if (port_state != HUB_PORT_STATE_SUSPENDED) {
-				rc = EOK;
-				break;
-			}
-			hub_set_port_state(hub, port, HUB_PORT_STATE_RESUMING);
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_PORT_POWER:
-			if (port_state != HUB_PORT_STATE_NOT_CONFIGURED) {
-				hub_set_port_state(hub, port, HUB_PORT_STATE_POWERED_OFF);
-			}
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_C_PORT_CONNECTION:
-			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_CONNECTION);
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_C_PORT_ENABLE:
-			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_ENABLE);
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_C_PORT_SUSPEND:
-			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_SUSPEND);
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_C_PORT_OVER_CURRENT:
-			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_OVER_CURRENT);
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_C_PORT_RESET:
-			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_RESET);
-			rc = EOK;
-			break;
-
-		default:
-			rc = ENOTSUP;
-			break;
-	}
-
-	hub_release(hub);
-
-	return rc;
-}
-
-/** Handle GetBusState request.
- *
- * @param dev Virtual device representing the hub.
- * @param request The SETUP packet of the control request.
- * @param data Extra data (when DATA stage present).
- * @return Error code.
- */
-static int req_get_bus_state(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *request, uint8_t *data,
-    size_t *act_size)
-{
-	return ENOTSUP;
-}
-
-/** Handle GetDescriptor request.
- *
- * @param dev Virtual device representing the hub.
- * @param request The SETUP packet of the control request.
- * @param data Extra data (when DATA stage present).
- * @return Error code.
- */
-static int req_get_descriptor(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *request, uint8_t *data,
-    size_t *act_size)
-{
-	if (request->value_high == USB_DESCTYPE_HUB) {
-		usbvirt_control_reply_helper(request, data, act_size,
-		    &hub_descriptor, hub_descriptor.length);
-
-		return EOK;
-	}
-	/* Let the framework handle all the rest. */
-	return EFORWARD;
-}
-
-/** Handle GetHubStatus request.
- *
- * @param dev Virtual device representing the hub.
- * @param request The SETUP packet of the control request.
- * @param data Extra data (when DATA stage present).
- * @return Error code.
- */
-static int req_get_hub_status(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *request, uint8_t *data,
-    size_t *act_size)
-{
-	uint32_t hub_status = 0;
-
-	usbvirt_control_reply_helper(request, data, act_size,
-	    &hub_status, sizeof(hub_status));
-
-	return EOK;
-}
-
-/** Handle GetPortStatus request.
- *
- * @param dev Virtual device representing the hub.
- * @param request The SETUP packet of the control request.
- * @param data Extra data (when DATA stage present).
- * @return Error code.
- */
-static int req_get_port_status(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *request, uint8_t *data,
-    size_t *act_size)
-{
-	hub_t *hub = (hub_t *) dev->device_data;
-
-	hub_acquire(hub);
-
-	uint32_t status = hub_get_port_status(hub, request->index - 1);
-
-	hub_release(hub);
-
-	usbvirt_control_reply_helper(request, data, act_size,
-	    &status, sizeof(status));
-
-	return EOK;
-}
-
-/** Handle SetHubFeature request.
- *
- * @param dev Virtual device representing the hub.
- * @param request The SETUP packet of the control request.
- * @param data Extra data (when DATA stage present).
- * @return Error code.
- */
-static int req_set_hub_feature(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *request, uint8_t *data,
-    size_t *act_size)
-{
-	return ENOTSUP;
-}
-
-/** Handle SetPortFeature request.
- *
- * @param dev Virtual device representing the hub.
- * @param request The SETUP packet of the control request.
- * @param data Extra data (when DATA stage present).
- * @return Error code.
- */
-static int req_set_port_feature(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *request, uint8_t *data,
-    size_t *act_size)
-{
-	int rc;
-	size_t port = request->index - 1;
-	usb_hub_class_feature_t feature = request->value;
-	hub_t *hub = (hub_t *) dev->device_data;
-
-	hub_acquire(hub);
-
-	hub_port_state_t port_state = hub_get_port_state(hub, port);
-
-	switch (feature) {
-		case USB_HUB_FEATURE_PORT_RESET:
-			if (port_state != HUB_PORT_STATE_POWERED_OFF) {
-				hub_set_port_state(hub, port, HUB_PORT_STATE_RESETTING);
-			}
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_PORT_SUSPEND:
-			if (port_state == HUB_PORT_STATE_ENABLED) {
-				hub_set_port_state(hub, port, HUB_PORT_STATE_SUSPENDED);
-			}
-			rc = EOK;
-			break;
-
-		case USB_HUB_FEATURE_PORT_POWER:
-			if (port_state == HUB_PORT_STATE_POWERED_OFF) {
-				hub_set_port_state(hub, port, HUB_PORT_STATE_DISCONNECTED);
-			}
-			rc = EOK;
-			break;
-
-		default:
-			break;
-	}
-
-	hub_release(hub);
-
-	return rc;
-}
-
-
-/** IN class request. */
-#define CLASS_REQ_IN(recipient) \
-	USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_IN, \
-	USBVIRT_REQUEST_TYPE_CLASS, recipient)
-/** OUT class request. */
-#define CLASS_REQ_OUT(recipient) \
-	USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_OUT, \
-	USBVIRT_REQUEST_TYPE_CLASS, recipient)
-
-/** Recipient: other. */
-#define REC_OTHER USB_REQUEST_RECIPIENT_OTHER
-/** Recipient: device. */
-#define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE
-/** Direction: in. */
-#define DIR_IN USB_DIRECTION_IN
-/** Direction: out. */
-#define DIR_OUT USB_DIRECTION_OUT
-
-
-/** Create a class request.
- *
- * @param direction Request direction.
- * @param recipient Request recipient.
- * @param req Request code.
- */
-#define CLASS_REQ(direction, recipient, req) \
-	.req_direction = direction, \
-	.req_recipient = recipient, \
-	.req_type = USB_REQUEST_TYPE_CLASS, \
-	.request = req
-
-/** Create a standard request.
- *
- * @param direction Request direction.
- * @param recipient Request recipient.
- * @param req Request code.
- */
-#define STD_REQ(direction, recipient, req) \
-	.req_direction = direction, \
-	.req_recipient = recipient, \
-	.req_type = USB_REQUEST_TYPE_STANDARD, \
-	.request = req
-
-/** Hub operations on control endpoint zero. */
-static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
-	{
-		STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
-		.name = "GetDescriptor",
-		.callback = req_get_descriptor
-	},
-	{
-		CLASS_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
-		.name = "GetDescriptor",
-		.callback = req_get_descriptor
-	},
-	{
-		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
-		.name = "GetPortStatus",
-		.callback = req_get_port_status
-	},
-	{
-		CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
-		.name = "ClearHubFeature",
-		.callback = req_clear_hub_feature
-	},
-	{
-		CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
-		.name = "ClearPortFeature",
-		.callback = req_clear_port_feature
-	},
-	{
-		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATE),
-		.name = "GetBusState",
-		.callback = req_get_bus_state
-	},
-	{
-		CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
-		.name = "GetHubDescriptor",
-		.callback = req_get_descriptor
-	},
-	{
-		CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),
-		.name = "GetHubStatus",
-		.callback = req_get_hub_status
-	},
-	{
-		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
-		.name = "GetPortStatus",
-		.callback = req_get_port_status
-	},
-	{
-		CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
-		.name = "SetHubFeature",
-		.callback = req_set_hub_feature
-	},
-	{
-		CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),
-		.name = "SetPortFeature",
-		.callback = req_set_port_feature
-	},
-	{
-		.callback = NULL
-	}
-};
-
-
-/** Hub operations. */
-usbvirt_device_ops_t hub_ops = {
-	.control = endpoint_zero_handlers,
-	.data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe,
-	.state_changed = on_state_change,
-};
-
-/**
- * @}
- */
Index: pace/drv/vhc/main.c
===================================================================
--- uspace/drv/vhc/main.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,153 +1,0 @@
-/*
- * 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 drvusbvhc
- * @{
- */
-/** @file
- * Virtual host controller.
- */
-
-#include <devmap.h>
-#include <async.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/driver.h>
-
-#include <usb/usb.h>
-#include <usb/ddfiface.h>
-#include <usb_iface.h>
-#include "vhcd.h"
-#include "hub.h"
-#include "conn.h"
-
-static ddf_dev_ops_t vhc_ops = {
-	.interfaces[USBHC_DEV_IFACE] = &vhc_iface,
-	.interfaces[USB_DEV_IFACE] = &vhc_usb_iface,
-	.close = on_client_close,
-	.default_handler = default_connection_handler
-};
-
-static int vhc_add_device(ddf_dev_t *dev)
-{
-	static int vhc_count = 0;
-	int rc;
-
-	if (vhc_count > 0) {
-		return ELIMIT;
-	}
-
-	vhc_data_t *data = malloc(sizeof(vhc_data_t));
-	if (data == NULL) {
-		usb_log_fatal("Failed to allocate memory.\n");
-		return ENOMEM;
-	}
-	data->magic = 0xDEADBEEF;
-	rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1);
-	if (rc != EOK) {
-		usb_log_fatal("Failed to initialize endpoint manager.\n");
-		free(data);
-		return rc;
-	}
-	usb_device_keeper_init(&data->dev_keeper);
-
-	ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
-	if (hc == NULL) {
-		usb_log_fatal("Failed to create device function.\n");
-		free(data);
-		return ENOMEM;
-	}
-
-	hc->ops = &vhc_ops;
-	list_initialize(&data->devices);
-	fibril_mutex_initialize(&data->guard);
-	data->hub = &virtual_hub_device;
-	data->hc_fun = hc;
-
-	dev->driver_data = data;
-
-	rc = ddf_fun_bind(hc);
-	if (rc != EOK) {
-		usb_log_fatal("Failed to bind HC function: %s.\n",
-		    str_error(rc));
-		free(data);
-		return rc;
-	}
-
-	rc = ddf_fun_add_to_class(hc, USB_HC_DDF_CLASS_NAME);
-	if (rc != EOK) {
-		usb_log_fatal("Failed to add function to HC class: %s.\n",
-		    str_error(rc));
-		free(data);
-		return rc;
-	}
-
-	virtual_hub_device_init(hc);
-
-	usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
-	    (size_t) dev->handle, (size_t) hc->handle);
-
-
-
-	rc = vhc_virtdev_plug_hub(data, data->hub, NULL);
-	if (rc != EOK) {
-		usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc));
-		free(data);
-		return rc;
-	}
-
-	return EOK;
-}
-
-static driver_ops_t vhc_driver_ops = {
-	.add_device = vhc_add_device,
-};
-
-static driver_t vhc_driver = {
-	.name = NAME,
-	.driver_ops = &vhc_driver_ops
-};
-
-
-int main(int argc, char * argv[])
-{	
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-
-	printf(NAME ": virtual USB host controller driver.\n");
-
-	return ddf_driver_main(&vhc_driver);
-}
-
-
-/**
- * @}
- */
Index: pace/drv/vhc/transfer.c
===================================================================
--- uspace/drv/vhc/transfer.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,287 +1,0 @@
-/*
- * 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.
- */
-
-#include <errno.h>
-#include <str_error.h>
-#include <usbvirt/device.h>
-#include <usbvirt/ipc.h>
-#include "vhcd.h"
-
-vhc_transfer_t *vhc_transfer_create(usb_address_t address, usb_endpoint_t ep,
-    usb_direction_t dir, usb_transfer_type_t tr_type,
-    ddf_fun_t *fun, void *callback_arg)
-{
-	vhc_transfer_t *result = malloc(sizeof(vhc_transfer_t));
-	if (result == NULL) {
-		return NULL;
-	}
-	link_initialize(&result->link);
-	result->address = address;
-	result->endpoint = ep;
-	result->direction = dir;
-	result->transfer_type = tr_type;
-	result->setup_buffer = NULL;
-	result->setup_buffer_size = 0;
-	result->data_buffer = NULL;
-	result->data_buffer_size = 0;
-	result->ddf_fun = fun;
-	result->callback_arg = callback_arg;
-	result->callback_in = NULL;
-	result->callback_out = NULL;
-
-	usb_log_debug2("Created transfer %p (%d.%d %s %s)\n", result,
-	    address, ep, usb_str_transfer_type_short(tr_type),
-	    dir == USB_DIRECTION_IN ? "in" : "out");
-
-	return result;
-}
-
-static bool is_set_address_transfer(vhc_transfer_t *transfer)
-{
-	if (transfer->endpoint != 0) {
-		return false;
-	}
-	if (transfer->transfer_type != USB_TRANSFER_CONTROL) {
-		return false;
-	}
-	if (transfer->direction != USB_DIRECTION_OUT) {
-		return false;
-	}
-	if (transfer->setup_buffer_size != sizeof(usb_device_request_setup_packet_t)) {
-		return false;
-	}
-	usb_device_request_setup_packet_t *setup = transfer->setup_buffer;
-	if (setup->request_type != 0) {
-		return false;
-	}
-	if (setup->request != USB_DEVREQ_SET_ADDRESS) {
-		return false;
-	}
-
-	return true;
-}
-
-int vhc_virtdev_add_transfer(vhc_data_t *vhc, vhc_transfer_t *transfer)
-{
-	fibril_mutex_lock(&vhc->guard);
-
-	bool target_found = false;
-	list_foreach(vhc->devices, pos) {
-		vhc_virtdev_t *dev = list_get_instance(pos, vhc_virtdev_t, link);
-		fibril_mutex_lock(&dev->guard);
-		if (dev->address == transfer->address) {
-			if (target_found) {
-				usb_log_warning("Transfer would be accepted by more devices!\n");
-				goto next;
-			}
-			target_found = true;
-			list_append(&transfer->link, &dev->transfer_queue);
-		}
-next:
-		fibril_mutex_unlock(&dev->guard);
-	}
-
-	fibril_mutex_unlock(&vhc->guard);
-
-	if (target_found) {
-		return EOK;
-	} else {
-		return ENOENT;
-	}
-}
-
-static int process_transfer_local(vhc_transfer_t *transfer,
-    usbvirt_device_t *dev, size_t *actual_data_size)
-{
-	int rc;
-
-	if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
-		if (transfer->direction == USB_DIRECTION_IN) {
-			rc = usbvirt_control_read(dev,
-			    transfer->setup_buffer, transfer->setup_buffer_size,
-			    transfer->data_buffer, transfer->data_buffer_size,
-			    actual_data_size);
-		} else {
-			assert(transfer->direction == USB_DIRECTION_OUT);
-			rc = usbvirt_control_write(dev,
-			    transfer->setup_buffer, transfer->setup_buffer_size,
-			    transfer->data_buffer, transfer->data_buffer_size);
-		}
-	} else {
-		if (transfer->direction == USB_DIRECTION_IN) {
-			rc = usbvirt_data_in(dev, transfer->transfer_type,
-			    transfer->endpoint,
-			    transfer->data_buffer, transfer->data_buffer_size,
-			    actual_data_size);
-		} else {
-			assert(transfer->direction == USB_DIRECTION_OUT);
-			rc = usbvirt_data_out(dev, transfer->transfer_type,
-			    transfer->endpoint,
-			    transfer->data_buffer, transfer->data_buffer_size);
-		}
-	}
-
-	return rc;
-}
-
-static int process_transfer_remote(vhc_transfer_t *transfer,
-    async_sess_t *sess, size_t *actual_data_size)
-{
-	int rc;
-
-	if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
-		if (transfer->direction == USB_DIRECTION_IN) {
-			rc = usbvirt_ipc_send_control_read(sess,
-			    transfer->setup_buffer, transfer->setup_buffer_size,
-			    transfer->data_buffer, transfer->data_buffer_size,
-			    actual_data_size);
-		} else {
-			assert(transfer->direction == USB_DIRECTION_OUT);
-			rc = usbvirt_ipc_send_control_write(sess,
-			    transfer->setup_buffer, transfer->setup_buffer_size,
-			    transfer->data_buffer, transfer->data_buffer_size);
-		}
-	} else {
-		if (transfer->direction == USB_DIRECTION_IN) {
-			rc = usbvirt_ipc_send_data_in(sess, transfer->endpoint,
-			    transfer->transfer_type,
-			    transfer->data_buffer, transfer->data_buffer_size,
-			    actual_data_size);
-		} else {
-			assert(transfer->direction == USB_DIRECTION_OUT);
-			rc = usbvirt_ipc_send_data_out(sess, transfer->endpoint,
-			    transfer->transfer_type,
-			    transfer->data_buffer, transfer->data_buffer_size);
-		}
-	}
-
-	return rc;
-}
-
-static vhc_transfer_t *dequeue_first_transfer(vhc_virtdev_t *dev)
-{
-	assert(fibril_mutex_is_locked(&dev->guard));
-	assert(!list_empty(&dev->transfer_queue));
-
-	vhc_transfer_t *transfer = list_get_instance(dev->transfer_queue.next,
-	    vhc_transfer_t, link);
-	list_remove(&transfer->link);
-
-	return transfer;
-}
-
-
-static void execute_transfer_callback_and_free(vhc_transfer_t *transfer,
-    size_t data_transfer_size, int outcome)
-{
-	assert(outcome != ENAK);
-
-	usb_log_debug2("Transfer %p ended: %s.\n",
-	    transfer, str_error(outcome));
-
-	if (transfer->direction == USB_DIRECTION_IN) {
-		transfer->callback_in(transfer->ddf_fun, outcome,
-		    data_transfer_size, transfer->callback_arg);
-	} else {
-		assert(transfer->direction == USB_DIRECTION_OUT);
-		transfer->callback_out(transfer->ddf_fun, outcome,
-		    transfer->callback_arg);
-	}
-
-	free(transfer);
-}
-
-int vhc_transfer_queue_processor(void *arg)
-{
-	vhc_virtdev_t *dev = arg;
-	fibril_mutex_lock(&dev->guard);
-	while (dev->plugged) {
-		if (list_empty(&dev->transfer_queue)) {
-			fibril_mutex_unlock(&dev->guard);
-			async_usleep(10 * 1000);
-			fibril_mutex_lock(&dev->guard);
-			continue;
-		}
-
-		vhc_transfer_t *transfer = dequeue_first_transfer(dev);
-		fibril_mutex_unlock(&dev->guard);
-
-		int rc = EOK;
-		size_t data_transfer_size = 0;
-		if (dev->dev_sess) {
-			rc = process_transfer_remote(transfer, dev->dev_sess,
-			    &data_transfer_size);
-		} else if (dev->dev_local != NULL) {
-			rc = process_transfer_local(transfer, dev->dev_local,
-			    &data_transfer_size);
-		} else {
-			usb_log_warning("Device has no remote phone nor local node.\n");
-			rc = ESTALL;
-		}
-
-		usb_log_debug2("Transfer %p processed: %s.\n",
-		    transfer, str_error(rc));
-
-		fibril_mutex_lock(&dev->guard);
-		if (rc == EOK) {
-			if (is_set_address_transfer(transfer)) {
-				usb_device_request_setup_packet_t *setup
-				    = transfer->setup_buffer;
-				dev->address = setup->value;
-				usb_log_debug2("Address changed to %d\n",
-				    dev->address);
-			}
-		}
-		if (rc == ENAK) {
-			// FIXME: this will work only because we do
-			// not NAK control transfers but this is generally
-			// a VERY bad idea indeed
-			list_append(&transfer->link, &dev->transfer_queue);
-		}
-		fibril_mutex_unlock(&dev->guard);
-
-		if (rc != ENAK) {
-			execute_transfer_callback_and_free(transfer,
-			    data_transfer_size, rc);
-		}
-
-		async_usleep(1000 * 100);
-		fibril_mutex_lock(&dev->guard);
-	}
-
-	/* Immediately fail all remaining transfers. */
-	while (!list_empty(&dev->transfer_queue)) {
-		vhc_transfer_t *transfer = dequeue_first_transfer(dev);
-		execute_transfer_callback_and_free(transfer, 0, EBADCHECKSUM);
-	}
-
-	fibril_mutex_unlock(&dev->guard);
-
-	return EOK;
-}
-
Index: pace/drv/vhc/vhc.ma
===================================================================
--- uspace/drv/vhc/vhc.ma	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,2 +1,0 @@
-10 usb&hc=vhc
-
Index: pace/drv/vhc/vhcd.h
===================================================================
--- uspace/drv/vhc/vhcd.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,97 +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 drvusbvhc
- * @{
- */
-/** @file
- * @brief Virtual USB host controller common definitions.
- */
-#ifndef VHCD_VHCD_H_
-#define VHCD_VHCD_H_
-
-#include <usb/debug.h>
-#include <usbvirt/device.h>
-#include <usb/host/usb_endpoint_manager.h>
-#include <usb/host/device_keeper.h>
-#include <usbhc_iface.h>
-#include <async.h>
-
-#define NAME "vhc"
-
-typedef struct {
-	link_t link;
-	async_sess_t *dev_sess;
-	usbvirt_device_t *dev_local;
-	bool plugged;
-	usb_address_t address;
-	fibril_mutex_t guard;
-	link_t transfer_queue;
-} vhc_virtdev_t;
-
-typedef struct {
-	uint32_t magic;
-	link_t devices;
-	fibril_mutex_t guard;
-	usb_endpoint_manager_t ep_manager;
-	usb_device_keeper_t dev_keeper;
-	usbvirt_device_t *hub;
-	ddf_fun_t *hc_fun;
-} vhc_data_t;
-
-typedef struct {
-	link_t link;
-	usb_address_t address;
-	usb_endpoint_t endpoint;
-	usb_direction_t direction;
-	usb_transfer_type_t transfer_type;
-	void *setup_buffer;
-	size_t setup_buffer_size;
-	void *data_buffer;
-	size_t data_buffer_size;
-	ddf_fun_t *ddf_fun;
-	void *callback_arg;
-	usbhc_iface_transfer_in_callback_t callback_in;
-	usbhc_iface_transfer_out_callback_t callback_out;
-} vhc_transfer_t;
-
-vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t,
-    usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *);
-int vhc_virtdev_plug(vhc_data_t *, async_sess_t *, uintptr_t *);
-int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
-int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
-void vhc_virtdev_unplug(vhc_data_t *, uintptr_t);
-int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *);
-
-int vhc_transfer_queue_processor(void *arg);
-
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/block/libblock.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -60,5 +60,5 @@
 static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
 /** Device connection list head. */
-static LIST_INITIALIZE(dcl_head);
+static LIST_INITIALIZE(dcl);
 
 #define CACHE_BUCKETS_LOG2  10
@@ -72,5 +72,5 @@
 	unsigned blocks_cached;   /**< Number of cached blocks. */
 	hash_table_t block_hash;
-	link_t free_head;
+	list_t free_list;
 	enum cache_mode mode;
 } cache_t;
@@ -97,9 +97,7 @@
 static devcon_t *devcon_search(devmap_handle_t devmap_handle)
 {
-	link_t *cur;
-	
 	fibril_mutex_lock(&dcl_lock);
 	
-	for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
+	list_foreach(dcl, cur) {
 		devcon_t *devcon = list_get_instance(cur, devcon_t, link);
 		if (devcon->devmap_handle == devmap_handle) {
@@ -116,5 +114,4 @@
     size_t bsize, void *comm_area, size_t comm_size)
 {
-	link_t *cur;
 	devcon_t *devcon;
 	
@@ -138,5 +135,5 @@
 	
 	fibril_mutex_lock(&dcl_lock);
-	for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
+	list_foreach(dcl, cur) {
 		devcon_t *d = list_get_instance(cur, devcon_t, link);
 		if (d->devmap_handle == devmap_handle) {
@@ -146,5 +143,5 @@
 		}
 	}
-	list_append(&devcon->link, &dcl_head);
+	list_append(&devcon->link, &dcl);
 	fibril_mutex_unlock(&dcl_lock);
 	return EOK;
@@ -294,5 +291,5 @@
 	
 	fibril_mutex_initialize(&cache->lock);
-	list_initialize(&cache->free_head);
+	list_initialize(&cache->free_list);
 	cache->lblock_size = size;
 	cache->block_count = blocks;
@@ -335,6 +332,6 @@
 	 * bother with the cache and block locks because we are single-threaded.
 	 */
-	while (!list_empty(&cache->free_head)) {
-		block_t *b = list_get_instance(cache->free_head.next,
+	while (!list_empty(&cache->free_list)) {
+		block_t *b = list_get_instance(list_first(&cache->free_list),
 		    block_t, free_link);
 
@@ -367,5 +364,5 @@
 	if (cache->blocks_cached < CACHE_LO_WATERMARK)
 		return true;
-	if (!list_empty(&cache->free_head))
+	if (!list_empty(&cache->free_list))
 		return false;
 	return true;
@@ -456,10 +453,10 @@
 			unsigned long temp_key;
 recycle:
-			if (list_empty(&cache->free_head)) {
+			if (list_empty(&cache->free_list)) {
 				fibril_mutex_unlock(&cache->lock);
 				rc = ENOMEM;
 				goto out;
 			}
-			l = cache->free_head.next;
+			l = list_first(&cache->free_list);
 			b = list_get_instance(l, block_t, free_link);
 
@@ -476,5 +473,5 @@
 				 */
 				list_remove(&b->free_link);
-				list_append(&b->free_link, &cache->free_head);
+				list_append(&b->free_link, &cache->free_list);
 				fibril_mutex_unlock(&cache->lock);
 				fibril_mutex_lock(&devcon->comm_area_lock);
@@ -668,5 +665,5 @@
 			goto retry;
 		}
-		list_append(&block->free_link, &cache->free_head);
+		list_append(&block->free_link, &cache->free_list);
 	}
 	fibril_mutex_unlock(&block->lock);
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -68,5 +68,4 @@
 	generic/clipboard.c \
 	generic/devmap.c \
-	generic/devmap_obsolete.c \
 	generic/devman.c \
 	generic/devman_obsolete.c \
Index: uspace/lib/c/generic/adt/hash_table.c
===================================================================
--- uspace/lib/c/generic/adt/hash_table.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/adt/hash_table.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -61,9 +61,9 @@
 	assert(max_keys > 0);
 	
-	h->entry = malloc(m * sizeof(link_t));
+	h->entry = malloc(m * sizeof(list_t));
 	if (!h->entry)
 		return false;
 	
-	memset((void *) h->entry, 0,  m * sizeof(link_t));
+	memset((void *) h->entry, 0,  m * sizeof(list_t));
 	
 	hash_count_t i;
@@ -123,7 +123,5 @@
 	assert(chain < h->entries);
 	
-	link_t *cur;
-	for (cur = h->entry[chain].next; cur != &h->entry[chain];
-	    cur = cur->next) {
+	list_foreach(h->entry[chain], cur) {
 		if (h->op->compare(key, h->max_keys, cur)) {
 			/*
@@ -153,7 +151,7 @@
 	assert(keys <= h->max_keys);
 	
-	link_t *cur;
-	
 	if (keys == h->max_keys) {
+		link_t *cur;
+		
 		/*
 		 * All keys are known, hash_table_find() can be used to find the
@@ -176,5 +174,7 @@
 	hash_index_t chain;
 	for (chain = 0; chain < h->entries; chain++) {
-		for (cur = h->entry[chain].next; cur != &h->entry[chain];
+		link_t *cur;
+		
+		for (cur = h->entry[chain].head.next; cur != &h->entry[chain].head;
 		    cur = cur->next) {
 			if (h->op->compare(key, keys, cur)) {
@@ -203,9 +203,7 @@
 {
 	hash_index_t bucket;
-	link_t *cur;
 	
 	for (bucket = 0; bucket < h->entries; bucket++) {
-		for (cur = h->entry[bucket].next; cur != &h->entry[bucket];
-		    cur = cur->next) {
+		list_foreach(h->entry[bucket], cur) {
 			f(cur, arg);
 		}
Index: uspace/lib/c/generic/adt/list.c
===================================================================
--- uspace/lib/c/generic/adt/list.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/adt/list.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -30,29 +30,35 @@
  * @{
  */
-/** @file
+
+/**
+ * @file
+ * @brief	Functions completing doubly linked circular list implementaion.
+ *
+ * This file contains some of the functions implementing doubly linked circular lists.
+ * However, this ADT is mostly implemented in @ref list.h.
  */
 
 #include <adt/list.h>
-
+#include <bool.h>
 
 /** Check for membership
  *
- * Check whether link is contained in the list head.
- * The membership is defined as pointer equivalence.
+ * Check whether link is contained in a list.
+ * Membership is defined as pointer equivalence.
  *
- * @param link Item to look for.
- * @param head List to look in.
+ * @param link	Item to look for.
+ * @param list	List to look in.
  *
  * @return true if link is contained in head, false otherwise.
  *
  */
-int list_member(const link_t *link, const link_t *head)
+int list_member(const link_t *link, const list_t *list)
 {
-	int found = 0;
-	link_t *hlp = head->next;
+	bool found = false;
+	link_t *hlp = list->head.next;
 	
-	while (hlp != head) {
+	while (hlp != &list->head) {
 		if (hlp == link) {
-			found = 1;
+			found = true;
 			break;
 		}
@@ -63,27 +69,25 @@
 }
 
-
 /** Concatenate two lists
  *
- * Concatenate lists head1 and head2, producing a single
- * list head1 containing items from both (in head1, head2
- * order) and empty list head2.
+ * Concatenate lists @a list1 and @a list2, producing a single
+ * list @a list1 containing items from both (in @a list1, @a list2
+ * order) and empty list @a list2.
  *
- * @param head1 First list and concatenated output
- * @param head2 Second list and empty output.
+ * @param list1		First list and concatenated output
+ * @param list2 	Second list and empty output.
  *
  */
-void list_concat(link_t *head1, link_t *head2)
+void list_concat(list_t *list1, list_t *list2)
 {
-	if (list_empty(head2))
+	if (list_empty(list2))
 		return;
-	
-	head2->next->prev = head1->prev;
-	head2->prev->next = head1;
-	head1->prev->next = head2->next;
-	head1->prev = head2->prev;
-	list_initialize(head2);
+
+	list2->head.next->prev = list1->head.prev;
+	list2->head.prev->next = &list1->head;
+	list1->head.prev->next = list2->head.next;
+	list1->head.prev = list2->head.prev;
+	list_initialize(list2);
 }
-
 
 /** Count list items
@@ -91,17 +95,13 @@
  * Return the number of items in the list.
  *
- * @param link List to count.
- *
- * @return Number of items in the list.
- *
+ * @param list		List to count.
+ * @return		Number of items in the list.
  */
-unsigned int list_count(const link_t *link)
+unsigned int list_count(const list_t *list)
 {
 	unsigned int count = 0;
-	link_t *hlp = link->next;
 	
-	while (hlp != link) {
+	list_foreach(*list, link) {
 		count++;
-		hlp = hlp->next;
 	}
 	
Index: uspace/lib/c/generic/adt/prodcons.c
===================================================================
--- uspace/lib/c/generic/adt/prodcons.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/adt/prodcons.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -61,5 +61,5 @@
 		fibril_condvar_wait(&pc->cv, &pc->mtx);
 	
-	link_t *head = pc->list.next;
+	link_t *head = list_first(&pc->list);
 	list_remove(head);
 	
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/async.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -160,5 +160,5 @@
 	
 	/** Messages that should be delivered to this fibril. */
-	link_t msg_queue;
+	list_t msg_queue;
 	
 	/** Identification of the opening call. */
@@ -213,7 +213,7 @@
  * This function is defined as a weak symbol - to be redefined in user code.
  *
- * @param callid	Hash of the incoming call.
- * @param call		Data of the incoming call.
- * @param arg		Local argument
+ * @param callid Hash of the incoming call.
+ * @param call   Data of the incoming call.
+ * @param arg    Local argument
  *
  */
@@ -228,7 +228,7 @@
  * This function is defined as a weak symbol - to be redefined in user code.
  *
- * @param callid	Hash of the incoming call.
- * @param call  	Data of the incoming call.
- * @param arg		Local argument.
+ * @param callid Hash of the incoming call.
+ * @param call   Data of the incoming call.
+ * @param arg    Local argument.
  *
  */
@@ -361,6 +361,6 @@
 	wd->to_event.inlist = true;
 	
-	link_t *tmp = timeout_list.next;
-	while (tmp != &timeout_list) {
+	link_t *tmp = timeout_list.head.next;
+	while (tmp != &timeout_list.head) {
 		awaiter_t *cur
 		    = list_get_instance(tmp, awaiter_t, to_event.link);
@@ -372,5 +372,5 @@
 	}
 	
-	list_append(&wd->to_event.link, tmp);
+	list_insert_before(&wd->to_event.link, tmp);
 }
 
@@ -569,5 +569,5 @@
 	}
 	
-	msg_t *msg = list_get_instance(conn->msg_queue.next, msg_t, link);
+	msg_t *msg = list_get_instance(list_first(&conn->msg_queue), msg_t, link);
 	list_remove(&msg->link);
 	
@@ -675,6 +675,6 @@
 	while (!list_empty(&fibril_connection->msg_queue)) {
 		msg_t *msg =
-		    list_get_instance(fibril_connection->msg_queue.next, msg_t,
-		    link);
+		    list_get_instance(list_first(&fibril_connection->msg_queue),
+		    msg_t, link);
 		
 		list_remove(&msg->link);
@@ -709,5 +709,5 @@
  * @param cfibril       Fibril function that should be called upon opening the
  *                      connection.
- * @param carg		Extra argument to pass to the connection fibril
+ * @param carg          Extra argument to pass to the connection fibril
  *
  * @return New fibril id or NULL on failure.
@@ -806,6 +806,6 @@
 	futex_down(&async_futex);
 	
-	link_t *cur = timeout_list.next;
-	while (cur != &timeout_list) {
+	link_t *cur = list_first(&timeout_list);
+	while (cur != NULL) {
 		awaiter_t *waiter =
 		    list_get_instance(cur, awaiter_t, to_event.link);
@@ -813,6 +813,4 @@
 		if (tv_gt(&waiter->to_event.expires, &tv))
 			break;
-		
-		cur = cur->next;
 		
 		list_remove(&waiter->to_event.link);
@@ -828,4 +826,6 @@
 			fibril_add_ready(waiter->fid);
 		}
+		
+		cur = list_first(&timeout_list);
 	}
 	
@@ -854,6 +854,6 @@
 		suseconds_t timeout;
 		if (!list_empty(&timeout_list)) {
-			awaiter_t *waiter = list_get_instance(timeout_list.next,
-			    awaiter_t, to_event.link);
+			awaiter_t *waiter = list_get_instance(
+			    list_first(&timeout_list), awaiter_t, to_event.link);
 			
 			struct timeval tv;
@@ -1731,5 +1731,7 @@
 		 */
 		exch = (async_exch_t *)
-		    list_get_instance(sess->exch_list.next, async_exch_t, sess_link);
+		    list_get_instance(list_first(&sess->exch_list),
+		    async_exch_t, sess_link);
+		
 		list_remove(&exch->sess_link);
 		list_remove(&exch->global_link);
@@ -1743,6 +1745,6 @@
 			exch = (async_exch_t *) malloc(sizeof(async_exch_t));
 			if (exch != NULL) {
-				list_initialize(&exch->sess_link);
-				list_initialize(&exch->global_link);
+				link_initialize(&exch->sess_link);
+				link_initialize(&exch->global_link);
 				exch->sess = sess;
 				exch->phone = sess->phone;
@@ -1761,6 +1763,6 @@
 				exch = (async_exch_t *) malloc(sizeof(async_exch_t));
 				if (exch != NULL) {
-					list_initialize(&exch->sess_link);
-					list_initialize(&exch->global_link);
+					link_initialize(&exch->sess_link);
+					link_initialize(&exch->global_link);
 					exch->sess = sess;
 					exch->phone = phone;
@@ -1774,6 +1776,7 @@
 				 */
 				exch = (async_exch_t *)
-				    list_get_instance(inactive_exch_list.next, async_exch_t,
-				    global_link);
+				    list_get_instance(list_first(&inactive_exch_list),
+				    async_exch_t, global_link);
+				
 				list_remove(&exch->sess_link);
 				list_remove(&exch->global_link);
Index: uspace/lib/c/generic/async_obsolete.c
===================================================================
--- uspace/lib/c/generic/async_obsolete.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/async_obsolete.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -166,14 +166,4 @@
 }
 
-void async_obsolete_serialize_start(void)
-{
-	fibril_inc_sercount();
-}
-
-void async_obsolete_serialize_end(void)
-{
-	fibril_dec_sercount();
-}
-
 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
  *
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/devman.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -35,4 +35,5 @@
  */
 
+#include <adt/list.h>
 #include <str.h>
 #include <ipc/services.h>
@@ -231,8 +232,7 @@
 	}
 	
-	link_t *link = match_ids->ids.next;
 	match_id_t *match_id = NULL;
 	
-	while (link != &match_ids->ids) {
+	list_foreach(match_ids->ids, link) {
 		match_id = list_get_instance(link, match_id_t, link);
 		
@@ -255,6 +255,4 @@
 			return retval;
 		}
-		
-		link = link->next;
 	}
 	
Index: pace/lib/c/generic/devmap_obsolete.c
===================================================================
--- uspace/lib/c/generic/devmap_obsolete.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,114 +1,0 @@
-/*
- * Copyright (c) 2007 Josef Cejka
- * Copyright (c) 2009 Jiri Svoboda
- * 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.
- */
-
-#include <str.h>
-#include <ipc/services.h>
-#include <ns.h>
-#include <ns_obsolete.h>
-#include <ipc/devmap.h>
-#include <devmap_obsolete.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <errno.h>
-#include <malloc.h>
-#include <bool.h>
-
-static int devmap_phone_driver = -1;
-static int devmap_phone_client = -1;
-
-/** Get phone to device mapper task. */
-int devmap_obsolete_get_phone(devmap_interface_t iface, unsigned int flags)
-{
-	switch (iface) {
-	case DEVMAP_DRIVER:
-		if (devmap_phone_driver >= 0)
-			return devmap_phone_driver;
-		
-		if (flags & IPC_FLAG_BLOCKING)
-			devmap_phone_driver = service_obsolete_connect_blocking(SERVICE_DEVMAP,
-			    DEVMAP_DRIVER, 0);
-		else
-			devmap_phone_driver = service_obsolete_connect(SERVICE_DEVMAP,
-			    DEVMAP_DRIVER, 0);
-		
-		return devmap_phone_driver;
-	case DEVMAP_CLIENT:
-		if (devmap_phone_client >= 0)
-			return devmap_phone_client;
-		
-		if (flags & IPC_FLAG_BLOCKING)
-			devmap_phone_client = service_obsolete_connect_blocking(SERVICE_DEVMAP,
-			    DEVMAP_CLIENT, 0);
-		else
-			devmap_phone_client = service_obsolete_connect(SERVICE_DEVMAP,
-			    DEVMAP_CLIENT, 0);
-		
-		return devmap_phone_client;
-	default:
-		return -1;
-	}
-}
-
-void devmap_obsolete_hangup_phone(devmap_interface_t iface)
-{
-	switch (iface) {
-	case DEVMAP_DRIVER:
-		if (devmap_phone_driver >= 0) {
-			async_obsolete_hangup(devmap_phone_driver);
-			devmap_phone_driver = -1;
-		}
-		break;
-	case DEVMAP_CLIENT:
-		if (devmap_phone_client >= 0) {
-			async_obsolete_hangup(devmap_phone_client);
-			devmap_phone_client = -1;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-int devmap_obsolete_device_connect(devmap_handle_t handle, unsigned int flags)
-{
-	int phone;
-	
-	if (flags & IPC_FLAG_BLOCKING) {
-		phone = service_obsolete_connect_blocking(SERVICE_DEVMAP,
-		    DEVMAP_CONNECT_TO_DEVICE, handle);
-	} else {
-		phone = service_obsolete_connect(SERVICE_DEVMAP,
-		    DEVMAP_CONNECT_TO_DEVICE, handle);
-	}
-	
-	return phone;
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/fibril.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -222,5 +222,6 @@
 	fibril_t *dstf;
 	if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
-		dstf = list_get_instance(manager_list.next, fibril_t, link);
+		dstf = list_get_instance(list_first(&manager_list), fibril_t,
+		    link);
 		if (serialization_count && stype == FIBRIL_TO_MANAGER) {
 			serialized_threads++;
@@ -233,10 +234,10 @@
 	} else {
 		if (!list_empty(&serialized_list)) {
-			dstf = list_get_instance(serialized_list.next, fibril_t,
-			    link);
+			dstf = list_get_instance(list_first(&serialized_list),
+			    fibril_t, link);
 			serialized_threads--;
 		} else {
-			dstf = list_get_instance(ready_list.next, fibril_t,
-			    link);
+			dstf = list_get_instance(list_first(&ready_list),
+			    fibril_t, link);
 		}
 	}
@@ -326,5 +327,5 @@
 	
 	if (!list_empty(&manager_list))
-		list_remove(manager_list.next);
+		list_remove(list_first(&manager_list));
 	
 	futex_up(&fibril_futex);
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/fibril_synch.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -148,6 +148,6 @@
 		fibril_t *f;
 	
-		assert(!list_empty(&fm->waiters));
-		tmp = fm->waiters.next;
+		tmp = list_first(&fm->waiters);
+		assert(tmp != NULL);
 		wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
 		wdp->active = true;
@@ -279,5 +279,5 @@
 	
 	while (!list_empty(&frw->waiters)) {
-		link_t *tmp = frw->waiters.next;
+		link_t *tmp = list_first(&frw->waiters);
 		awaiter_t *wdp;
 		fibril_t *f;
@@ -422,5 +422,5 @@
 	futex_down(&async_futex);
 	while (!list_empty(&fcv->waiters)) {
-		tmp = fcv->waiters.next;
+		tmp = list_first(&fcv->waiters);
 		wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
 		list_remove(&wdp->wu_event.link);
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/io/io.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -127,10 +127,7 @@
 void __stdio_done(void)
 {
-	link_t *link = files.next;
-	
-	while (link != &files) {
-		FILE *file = list_get_instance(link, FILE, link);
+	while (!list_empty(&files)) {
+		FILE *file = list_get_instance(list_first(&files), FILE, link);
 		fclose(file);
-		link = files.next;
 	}
 }
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/ipc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -458,5 +458,5 @@
 	while (!list_empty(&queued_calls)) {
 		async_call_t *call =
-		    list_get_instance(queued_calls.next, async_call_t, list);
+		    list_get_instance(list_first(&queued_calls), async_call_t, list);
 		ipc_callid_t callid =
 		    ipc_call_async_internal(call->u.msg.phoneid, &call->u.msg.data);
@@ -511,5 +511,5 @@
 	
 	link_t *item;
-	for (item = dispatched_calls.next; item != &dispatched_calls;
+	for (item = dispatched_calls.head.next; item != &dispatched_calls.head;
 	    item = item->next) {
 		async_call_t *call =
Index: uspace/lib/c/generic/net/icmp_common.c
===================================================================
--- uspace/lib/c/generic/net/icmp_common.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/net/icmp_common.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -45,14 +45,10 @@
 /** Connect to the ICMP module.
  *
- * @param[in] timeout Connection timeout in microseconds, zero
- *                    for no timeout.
- *
  * @return ICMP module phone on success.
- * @return ETIMEOUT if the connection timeouted.
  *
  */
-int icmp_connect_module(suseconds_t timeout)
+int icmp_connect_module(void)
 {
-	return connect_to_service_timeout(SERVICE_ICMP, timeout);
+	return connect_to_service(SERVICE_ICMP);
 }
 
Index: uspace/lib/c/generic/net/modules.c
===================================================================
--- uspace/lib/c/generic/net/modules.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/net/modules.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -114,29 +114,6 @@
     async_client_conn_t client_receiver)
 {
-	return bind_service_timeout(need, arg1, arg2, arg3, client_receiver, 0);
-}
-
-/** Create bidirectional connection with the needed module service and registers
- * the message receiver.
- *
- * @param[in] need	The needed module service.
- * @param[in] arg1	The first parameter.
- * @param[in] arg2	The second parameter.
- * @param[in] arg3	The third parameter.
- * @param[in] client_receiver The message receiver.
- * @param[in] timeout	The connection timeout in microseconds. No timeout if
- * 			set to zero (0).
- *
- * @return		The phone of the needed service.
- * @return		ETIMEOUT if the connection timeouted.
- * @return		Other error codes as defined for the ipc_connect_to_me()
- *			function.
- *
- */
-int bind_service_timeout(services_t need, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, async_client_conn_t client_receiver, suseconds_t timeout)
-{
 	/* Connect to the needed service */
-	int phone = connect_to_service_timeout(need, timeout);
+	int phone = connect_to_service(need);
 	if (phone >= 0) {
 		/* Request the bidirectional connection */
@@ -159,37 +136,5 @@
 int connect_to_service(services_t need)
 {
-	return connect_to_service_timeout(need, 0);
-}
-
-/** Connects to the needed module.
- *
- *  @param[in] need	The needed module service.
- *  @param[in] timeout	The connection timeout in microseconds. No timeout if
- *			set to zero (0).
- *  @return		The phone of the needed service.
- *  @return		ETIMEOUT if the connection timeouted.
- */
-int connect_to_service_timeout(services_t need, suseconds_t timeout)
-{
-	int phone;
-
-	/* If no timeout is set */
-	if (timeout <= 0)
-		return service_obsolete_connect_blocking(need, 0, 0);
-	
-	while (true) {
-		phone = service_obsolete_connect(need, 0, 0);
-		if ((phone >= 0) || (phone != ENOENT))
-			return phone;
-
-		/* Abort if no time is left */
-		if (timeout <= 0)
-			return ETIMEOUT;
-
-		/* Wait the minimum of the module wait time and the timeout */
-		usleep((timeout <= MODULE_WAIT_TIME) ?
-		    timeout : MODULE_WAIT_TIME);
-		timeout -= MODULE_WAIT_TIME;
-	}
+	return service_obsolete_connect_blocking(need, 0, 0);
 }
 
Index: uspace/lib/c/generic/net/socket_client.c
===================================================================
--- uspace/lib/c/generic/net/socket_client.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/net/socket_client.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -64,7 +64,4 @@
 /** Maximum waiting sockets queue size. */
 #define SOCKET_MAX_ACCEPTED_SIZE	0
-
-/** Default timeout for connections in microseconds. */
-#define SOCKET_CONNECT_TIMEOUT	(1 * 1000 * 1000)
 
 /**
@@ -289,12 +286,11 @@
  * @return		The TCP module phone.
  * @return		Other error codes as defined for the
- *			bind_service_timeout() function.
+ *			bind_service() function.
  */
 static int socket_get_tcp_phone(void)
 {
 	if (socket_globals.tcp_phone < 0) {
-		socket_globals.tcp_phone = bind_service_timeout(SERVICE_TCP,
-		    0, 0, SERVICE_TCP, socket_connection,
-		    SOCKET_CONNECT_TIMEOUT);
+		socket_globals.tcp_phone = bind_service(SERVICE_TCP,
+		    0, 0, SERVICE_TCP, socket_connection);
 	}
 
@@ -308,12 +304,11 @@
  * @return		The UDP module phone.
  * @return		Other error codes as defined for the
- *			bind_service_timeout() function.
+ *			bind_service() function.
  */
 static int socket_get_udp_phone(void)
 {
 	if (socket_globals.udp_phone < 0) {
-		socket_globals.udp_phone = bind_service_timeout(SERVICE_UDP,
-		    0, 0, SERVICE_UDP, socket_connection,
-		    SOCKET_CONNECT_TIMEOUT);
+		socket_globals.udp_phone = bind_service(SERVICE_UDP,
+		    0, 0, SERVICE_UDP, socket_connection);
 	}
 
@@ -397,5 +392,5 @@
  * @return		Other error codes as defined for the NET_SOCKET message.
  * @return		Other error codes as defined for the
- *			bind_service_timeout() function.
+ *			bind_service() function.
  */
 int socket(int domain, int type, int protocol)
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/str.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -540,4 +540,7 @@
 
 	dstr_size = str_size(dest);
+	if (dstr_size >= size)
+		return;
+	
 	str_cpy(dest + dstr_size, size - dstr_size, src);
 }
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/generic/task.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -190,4 +190,5 @@
 	
 	return EOK;
+	
 error:
 	/* Error exit */
Index: uspace/lib/c/include/adt/hash_table.h
===================================================================
--- uspace/lib/c/include/adt/hash_table.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/adt/hash_table.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -75,5 +75,5 @@
 /** Hash table structure. */
 typedef struct {
-	link_t *entry;
+	list_t *entry;
 	hash_count_t entries;
 	hash_count_t max_keys;
Index: uspace/lib/c/include/adt/list.h
===================================================================
--- uspace/lib/c/include/adt/list.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/adt/list.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,7 +37,8 @@
 #define LIBC_LIST_H_
 
+#include <assert.h>
 #include <unistd.h>
 
-/** Doubly linked list head and link type. */
+/** Doubly linked list link. */
 typedef struct link {
 	struct link *prev;  /**< Pointer to the previous item in the list. */
@@ -44,4 +46,9 @@
 } link_t;
 
+/** Doubly linked list. */
+typedef struct list {
+	link_t head;  /**< List head. Does not have any data. */
+} list_t;
+
 /** Declare and initialize statically allocated list.
  *
@@ -50,7 +57,9 @@
  */
 #define LIST_INITIALIZE(name) \
-	link_t name = { \
-		.prev = &name, \
-		.next = &name \
+	list_t name = { \
+		.head = { \
+			.prev = &(name).head, \
+			.next = &(name).head \
+		} \
 	}
 
@@ -59,6 +68,9 @@
 
 #define list_foreach(list, iterator) \
-	for (link_t *iterator = (list).next; \
-	    iterator != &(list); iterator = iterator->next)
+	for (link_t *iterator = (list).head.next; \
+	    iterator != &(list).head; iterator = iterator->next)
+
+#define assert_link_not_used(link) \
+	assert((link)->prev == NULL && (link)->next == NULL)
 
 /** Initialize doubly-linked circular list link
@@ -79,11 +91,33 @@
  * Initialize doubly-linked circular list.
  *
- * @param list Pointer to link_t structure representing the list.
- *
- */
-static inline void list_initialize(link_t *list)
-{
-	list->prev = list;
-	list->next = list;
+ * @param list Pointer to list_t structure.
+ *
+ */
+static inline void list_initialize(list_t *list)
+{
+	list->head.prev = &list->head;
+	list->head.next = &list->head;
+}
+
+/** Insert item before another item in doubly-linked circular list.
+ *
+ */
+static inline void list_insert_before(link_t *lnew, link_t *lold)
+{
+	lnew->next = lold;
+	lnew->prev = lold->prev;
+	lold->prev->next = lnew;
+	lold->prev = lnew;
+}
+
+/** Insert item after another item in doubly-linked circular list.
+ *
+ */
+static inline void list_insert_after(link_t *lnew, link_t *lold)
+{
+	lnew->prev = lold;
+	lnew->next = lold->next;
+	lold->next->prev = lnew;
+	lold->next = lnew;
 }
 
@@ -93,13 +127,10 @@
  *
  * @param link Pointer to link_t structure to be added.
- * @param list Pointer to link_t structure representing the list.
- *
- */
-static inline void list_prepend(link_t *link, link_t *list)
-{
-	link->next = list->next;
-	link->prev = list;
-	list->next->prev = link;
-	list->next = link;
+ * @param list Pointer to list_t structure.
+ *
+ */
+static inline void list_prepend(link_t *link, list_t *list)
+{
+	list_insert_after(link, &list->head);
 }
 
@@ -109,29 +140,10 @@
  *
  * @param link Pointer to link_t structure to be added.
- * @param list Pointer to link_t structure representing the list.
- *
- */
-static inline void list_append(link_t *link, link_t *list)
-{
-	link->prev = list->prev;
-	link->next = list;
-	list->prev->next = link;
-	list->prev = link;
-}
-
-/** Insert item before another item in doubly-linked circular list.
- *
- */
-static inline void list_insert_before(link_t *link, link_t *list)
-{
-	list_append(link, list);
-}
-
-/** Insert item after another item in doubly-linked circular list.
- *
- */
-static inline void list_insert_after(link_t *link, link_t *list)
-{
-	list_prepend(list, link);
+ * @param list Pointer to list_t structure.
+ *
+ */
+static inline void list_append(link_t *link, list_t *list)
+{
+	list_insert_before(link, &list->head);
 }
 
@@ -155,15 +167,15 @@
  * Query emptiness of doubly-linked circular list.
  *
- * @param list Pointer to link_t structure representing the list.
- *
- */
-static inline int list_empty(link_t *list)
-{
-	return (list->next == list);
-}
-
-/** Get head item of a list.
- *
- * @param list Pointer to link_t structure representing the list.
+ * @param list Pointer to lins_t structure.
+ *
+ */
+static inline int list_empty(list_t *list)
+{
+	return (list->head.next == &list->head);
+}
+
+/** Get first item in list.
+ *
+ * @param list Pointer to list_t structure.
  *
  * @return Head item of the list.
@@ -171,7 +183,20 @@
  *
  */
-static inline link_t *list_head(link_t *list)
-{
-	return ((list->next == list) ? NULL : list->next);
+static inline link_t *list_first(list_t *list)
+{
+	return ((list->head.next == &list->head) ? NULL : list->head.next);
+}
+
+/** Get last item in list.
+ *
+ * @param list Pointer to list_t structure.
+ *
+ * @return Head item of the list.
+ * @return NULL if the list is empty.
+ *
+ */
+static inline link_t *list_last(list_t *list)
+{
+	return ((list->head.prev == &list->head) ? NULL : list->head.prev);
 }
 
@@ -230,5 +255,5 @@
 }
 
-/** Get n-th item of a list.
+/** Get n-th item in a list.
  *
  * @param list Pointer to link_t structure representing the list.
@@ -239,5 +264,5 @@
  *
  */
-static inline link_t *list_nth(link_t *list, unsigned int n)
+static inline link_t *list_nth(list_t *list, unsigned int n)
 {
 	unsigned int cnt = 0;
@@ -253,7 +278,7 @@
 }
 
-extern int list_member(const link_t *, const link_t *);
-extern void list_concat(link_t *, link_t *);
-extern unsigned int list_count(const link_t *);
+extern int list_member(const link_t *, const list_t *);
+extern void list_concat(list_t *, list_t *);
+extern unsigned int list_count(const list_t *);
 
 #endif
Index: uspace/lib/c/include/adt/prodcons.h
===================================================================
--- uspace/lib/c/include/adt/prodcons.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/adt/prodcons.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -42,5 +42,5 @@
 	fibril_mutex_t mtx;
 	fibril_condvar_t cv;
-	link_t list;
+	list_t list;
 } prodcons_t;
 
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/async.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -55,9 +55,9 @@
 /** Client connection handler
  *
- * @param callid	ID of incoming call or 0 if connection initiated from
- *			inside using async_connect_to_me()
- * @param call		Incoming call or 0 if connection initiated from inside
- * @param arg		Local argument passed from async_new_connection() or
- *			async_connect_to_me()
+ * @param callid ID of incoming call or 0 if connection initiated from
+ *               inside using async_connect_to_me()
+ * @param call   Incoming call or 0 if connection initiated from inside
+ * @param arg    Local argument passed from async_new_connection() or
+ *               async_connect_to_me()
  */
 typedef void (*async_client_conn_t)(ipc_callid_t, ipc_call_t *, void *);
@@ -99,5 +99,5 @@
 typedef struct {
 	/** List of inactive exchanges */
-	link_t exch_list;
+	list_t exch_list;
 	
 	/** Exchange management style */
Index: uspace/lib/c/include/async_obsolete.h
===================================================================
--- uspace/lib/c/include/async_obsolete.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/async_obsolete.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -40,7 +40,4 @@
 #define LIBC_ASYNC_OBSOLETE_H_
 
-extern void async_obsolete_serialize_start(void);
-extern void async_obsolete_serialize_end(void);
-
 #define async_obsolete_send_0(phoneid, method, dataptr) \
 	async_obsolete_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
Index: pace/lib/c/include/devmap_obsolete.h
===================================================================
--- uspace/lib/c/include/devmap_obsolete.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_DEVMAP_OBSOLETE_H_
-#define LIBC_DEVMAP_OBSOLETE_H_
-
-#include <ipc/devmap.h>
-#include <async.h>
-#include <bool.h>
-
-extern int devmap_obsolete_get_phone(devmap_interface_t, unsigned int);
-extern void devmap_obsolete_hangup_phone(devmap_interface_t iface);
-
-extern int devmap_obsolete_device_connect(devmap_handle_t, unsigned int);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/fibril_synch.h
===================================================================
--- uspace/lib/c/include/fibril_synch.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/fibril_synch.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -45,5 +45,5 @@
 	fibril_owner_info_t oi;  /**< Keep this the first thing. */
 	int counter;
-	link_t waiters;
+	list_t waiters;
 } fibril_mutex_t;
 
@@ -55,6 +55,8 @@
 		.counter = 1, \
 		.waiters = { \
-			.prev = &name.waiters, \
-			.next = &name.waiters, \
+			.head = { \
+				.prev = &(name).waiters.head, \
+				.next = &(name).waiters.head, \
+			} \
 		} \
 	}
@@ -67,5 +69,5 @@
 	unsigned writers;
 	unsigned readers;
-	link_t waiters;
+	list_t waiters;
 } fibril_rwlock_t;
 
@@ -78,6 +80,8 @@
 		.writers = 0, \
 		.waiters = { \
-			.prev = &name.waiters, \
-			.next = &name.waiters, \
+			.head = { \
+				.prev = &(name).waiters.head, \
+				.next = &(name).waiters.head, \
+			} \
 		} \
 	}
@@ -87,5 +91,5 @@
 
 typedef struct {
-	link_t waiters;
+	list_t waiters;
 } fibril_condvar_t;
 
@@ -93,6 +97,8 @@
 	{ \
 		.waiters = { \
-			.next = &name.waiters, \
-			.prev = &name.waiters, \
+			.head = { \
+				.next = &(name).waiters.head, \
+				.prev = &(name).waiters.head, \
+			} \
 		} \
 	}
Index: uspace/lib/c/include/ipc/clipboard.h
===================================================================
--- uspace/lib/c/include/ipc/clipboard.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/ipc/clipboard.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -36,4 +36,6 @@
 #define LIBC_IPC_CLIPBOARD_H_
 
+#include <ipc/common.h>
+
 typedef enum {
 	CLIPBOARD_PUT_DATA = IPC_FIRST_USER_METHOD,
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/ipc/devman.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -72,5 +72,5 @@
  */
 typedef struct match_id_list {
-	link_t ids;
+	list_t ids;
 } match_id_list_t;
 
@@ -95,11 +95,11 @@
 {
 	match_id_t *mid = NULL;
-	link_t *link = ids->ids.next;
+	link_t *link = ids->ids.head.next;
 	
-	while (link != &ids->ids) {
+	while (link != &ids->ids.head) {
 		mid = list_get_instance(link, match_id_t,link);
 		if (mid->score < id->score) {
 			break;
-		}	
+		}
 		link = link->next;
 	}
@@ -118,10 +118,10 @@
 	match_id_t *id;
 	
-	while(!list_empty(&ids->ids)) {
-		link = ids->ids.next;
-		list_remove(link);		
+	while (!list_empty(&ids->ids)) {
+		link = list_first(&ids->ids);
+		list_remove(link);
 		id = list_get_instance(link, match_id_t, link);
-		delete_match_id(id);		
-	}	
+		delete_match_id(id);
+	}
 }
 
Index: pace/lib/c/include/ipc/mouse.h
===================================================================
--- uspace/lib/c/include/ipc/mouse.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_IPC_MOUSE_H_
-#define LIBC_IPC_MOUSE_H_
-
-#include <ipc/common.h>
-
-typedef enum {
-	MEVENT_BUTTON = IPC_FIRST_USER_METHOD,
-	MEVENT_MOVE
-} mouse_notif_t;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/c/include/ipc/mouseev.h
===================================================================
--- uspace/lib/c/include/ipc/mouseev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/lib/c/include/ipc/mouseev.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * 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 mouse
+ * @brief
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_MOUSEEV_H_
+#define LIBC_IPC_MOUSEEV_H_
+
+#include <ipc/common.h>
+#include <ipc/dev_iface.h>
+
+typedef enum {
+	MOUSEEV_YIELD = DEV_FIRST_CUSTOM_METHOD,
+	MOUSEEV_RECLAIM
+} mouseev_request_t;
+
+typedef enum {
+	MOUSEEV_MOVE_EVENT = IPC_FIRST_USER_METHOD,
+	MOUSEEV_BUTTON_EVENT
+} mouseev_notif_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/ipc/services.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -41,7 +41,5 @@
 	SERVICE_NONE = 0,
 	SERVICE_LOAD,
-	SERVICE_PCI,
 	SERVICE_VIDEO,
-	SERVICE_CONSOLE,
 	SERVICE_VFS,
 	SERVICE_DEVMAP,
@@ -56,9 +54,7 @@
 	SERVICE_IP,
 	SERVICE_ARP,
-	SERVICE_RARP,
 	SERVICE_ICMP,
 	SERVICE_UDP,
-	SERVICE_TCP,
-	SERVICE_SOCKET
+	SERVICE_TCP
 } services_t;
 
Index: uspace/lib/c/include/net/icmp_common.h
===================================================================
--- uspace/lib/c/include/net/icmp_common.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/net/icmp_common.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -41,8 +41,5 @@
 #include <sys/time.h>
 
-/** Default timeout for incoming connections in microseconds (1 sec). */
-#define ICMP_CONNECT_TIMEOUT  1000000
-
-extern int icmp_connect_module(suseconds_t);
+extern int icmp_connect_module(void);
 
 #endif
Index: uspace/lib/c/include/net/modules.h
===================================================================
--- uspace/lib/c/include/net/modules.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/c/include/net/modules.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -58,8 +58,5 @@
 extern int bind_service(services_t, sysarg_t, sysarg_t, sysarg_t,
     async_client_conn_t);
-extern int bind_service_timeout(services_t, sysarg_t, sysarg_t, sysarg_t,
-    async_client_conn_t, suseconds_t);
 extern int connect_to_service(services_t);
-extern int connect_to_service_timeout(services_t, suseconds_t);
 extern int data_reply(void *, size_t);
 extern void refresh_answer(ipc_call_t *, size_t *);
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/drv/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -36,4 +36,5 @@
 	generic/dev_iface.c \
 	generic/log.c \
+	generic/logbuf.c \
 	generic/remote_hw_res.c \
 	generic/remote_char_dev.c \
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/drv/generic/driver.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -139,10 +139,9 @@
 find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
 {
+	interrupt_context_t *ctx;
+	
 	fibril_mutex_lock(&list->mutex);
 	
-	link_t *link = list->contexts.next;
-	interrupt_context_t *ctx;
-	
-	while (link != &list->contexts) {
+	list_foreach(list->contexts, link) {
 		ctx = list_get_instance(link, interrupt_context_t, link);
 		if (ctx->id == id) {
@@ -150,5 +149,4 @@
 			return ctx;
 		}
-		link = link->next;
 	}
 	
@@ -160,10 +158,9 @@
 find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
 {
+	interrupt_context_t *ctx;
+	
 	fibril_mutex_lock(&list->mutex);
 	
-	link_t *link = list->contexts.next;
-	interrupt_context_t *ctx;
-	
-	while (link != &list->contexts) {
+	list_foreach(list->contexts, link) {
 		ctx = list_get_instance(link, interrupt_context_t, link);
 		if (ctx->irq == irq && ctx->dev == dev) {
@@ -171,5 +168,4 @@
 			return ctx;
 		}
-		link = link->next;
 	}
 	
@@ -231,12 +227,11 @@
 }
 
-static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle)
+static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle)
 {
 	ddf_fun_t *fun = NULL;
 	
 	fibril_mutex_lock(&functions_mutex);
-	link_t *link = functions->next;
-	
-	while (link != functions) {
+	
+	list_foreach(*functions, link) {
 		fun = list_get_instance(link, ddf_fun_t, link);
 		if (fun->handle == handle) {
@@ -244,6 +239,4 @@
 			return fun;
 		}
-		
-		link = link->next;
 	}
 	
Index: uspace/lib/drv/generic/logbuf.c
===================================================================
--- uspace/lib/drv/generic/logbuf.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/lib/drv/generic/logbuf.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,202 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+
+#include <libarch/common.h>
+#include <stdio.h>
+#include <ddf/log.h>
+#include <assert.h>
+
+/** Formatting string for printing number of not-printed items. */
+#define REMAINDER_STR_FMT " (%zu)..."
+/** Expected max size of the remainder string.
+ * String + terminator + number width (enough for 4GB).*/
+#define REMAINDER_STR_LEN (5 + 1 + 10)
+
+/** Groups size. */
+#define BUFFER_DUMP_GROUP_SIZE 4
+
+/** Space between two items. */
+#define SPACE_NORMAL " "
+/** Space between two groups. */
+#define SPACE_GROUP "  "
+
+/** Dump one item into given buffer.
+ *
+ * @param buffer Data buffer.
+ * @param item_size Size of the item (1, 2, 4).
+ * @param index Index into the @p buffer (respecting @p item_size).
+ * @param dump Where to store the dump.
+ * @param dump_size Size of @p dump size.
+ * @return Number of characters printed (see snprintf).
+ */
+static int dump_one_item(const void *buffer, size_t item_size, size_t index,
+    char *dump, size_t dump_size)
+{
+	/* Determine space before the number. */
+	const char *space_before;
+	if (index == 0) {
+		space_before = "";
+	} else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
+		space_before = SPACE_GROUP;
+	} else {
+		space_before = SPACE_NORMAL;
+	}
+
+	/* Let buf point to the item to be printed. */
+	const uint8_t *buf = (const uint8_t *) buffer;
+	buf += index * item_size;
+
+/* Formats the dump with space before, takes care of type casting (ugly). */
+#define _FORMAT(digits, bits) \
+	snprintf(dump, dump_size, "%s%0" #digits PRIx##bits, \
+	    space_before, ((uint##bits##_t *)buf)[0]);
+
+	switch (item_size) {
+	case 4:
+		return _FORMAT(8, 32);
+	case 2:
+		return _FORMAT(4, 16);
+	default:
+		return _FORMAT(2, 8);
+	}
+#undef _FORMAT
+}
+
+/** Count number of characters needed for dumping buffer of given size.
+ *
+ * @param item_size Item size in bytes.
+ * @param items Number of items to print.
+ * @return Number of characters the full dump would occupy.
+ */
+static size_t count_dump_length(size_t item_size, size_t items)
+{
+	size_t group_space_count = items / BUFFER_DUMP_GROUP_SIZE - 1;
+	size_t normal_space_count = items - 1 - group_space_count;
+
+	size_t dump_itself = item_size * 2 * items;
+	size_t group_spaces = str_size(SPACE_GROUP) * group_space_count;
+	size_t normal_spaces = str_size(SPACE_NORMAL) * normal_space_count;
+
+	return dump_itself + group_spaces + normal_spaces;
+}
+
+
+/** Dumps data buffer to a string in hexadecimal format.
+ *
+ * Setting @p items_to_print to zero would dump the whole buffer together
+ * with information how many items were omitted. Otherwise, no information
+ * about omitted items is printed.
+ *
+ * @param dump Where to store the dumped buffer.
+ * @param dump_size Size of @p dump in bytes.
+ * @param buffer Data buffer to be dumped.
+ * @param item_size Size of items in the @p buffer in bytes (1,2,4 allowed).
+ * @param items Number of items in the @p buffer.
+ * @param items_to_print How many items to actually print.
+ */
+void ddf_dump_buffer(char *dump, size_t dump_size,
+    const void *buffer, size_t item_size, size_t items, size_t items_to_print)
+{
+	if ((dump_size == 0) || (dump == NULL)) {
+		return;
+	}
+	/* We need space for one byte at least. */
+	if (dump_size < 3) {
+		str_cpy(dump, dump_size, "...");
+		return;
+	}
+
+	/* Special cases first. */
+	if (buffer == NULL) {
+		str_cpy(dump, dump_size, "(null)");
+		return;
+	}
+	if (items == 0) {
+		str_cpy(dump, dump_size, "(empty)");
+	}
+
+	if (items_to_print > items) {
+		items_to_print = items;
+	}
+
+	bool print_remainder = items_to_print == 0;
+
+	/* How many available bytes we do have. */
+	size_t dump_size_remaining = dump_size - 1;
+
+	if (print_remainder) {
+		/* Can't do much when user supplied small buffer. */
+		if (dump_size_remaining < REMAINDER_STR_LEN) {
+			print_remainder = false;
+		} else {
+			size_t needed_size = count_dump_length(item_size, items);
+			if (needed_size > dump_size_remaining) {
+				dump_size_remaining -= REMAINDER_STR_LEN;
+			} else {
+				print_remainder = false;
+			}
+		}
+		items_to_print = items;
+	}
+
+	str_cpy(dump, dump_size, "");
+
+	size_t index = 0;
+	while (index < items) {
+		char current_item[32];
+		int printed = dump_one_item(buffer, item_size, index,
+		    current_item, 32);
+		assert(printed >= 0);
+
+		if ((size_t) printed > dump_size_remaining) {
+			break;
+		}
+
+		str_append(dump, dump_size, current_item);
+
+		dump_size_remaining -= printed;
+		index++;
+
+		if (index >= items_to_print) {
+			break;
+		}
+	}
+
+	if (print_remainder && (index < items)) {
+		size_t s = str_size(dump);
+		snprintf(dump + s, dump_size - s ,REMAINDER_STR_FMT,
+		    items - index);
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/drv/include/ddf/interrupt.h
===================================================================
--- uspace/lib/drv/include/ddf/interrupt.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/drv/include/ddf/interrupt.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -60,5 +60,5 @@
 typedef struct interrupt_context_list {
 	int curr_id;
-	link_t contexts;
+	list_t contexts;
 	fibril_mutex_t mutex;
 } interrupt_context_list_t;
Index: uspace/lib/drv/include/ddf/log.h
===================================================================
--- uspace/lib/drv/include/ddf/log.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/drv/include/ddf/log.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -39,4 +39,7 @@
 extern void ddf_msg(log_level_t, const char *, ...);
 
+extern void ddf_dump_buffer(char *, size_t, const void *, size_t, size_t,
+    size_t);
+
 #endif
 
Index: uspace/lib/posix/Makefile
===================================================================
--- uspace/lib/posix/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/posix/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -40,5 +40,5 @@
 SOURCES = \
 	ctype.c \
-	getopt.c \
+	fcntl.c \
 	stdio.c \
 	stdlib.c \
Index: pace/lib/posix/fnmatch.c
===================================================================
--- uspace/lib/posix/fnmatch.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "fnmatch.h"
-
-/**
- * 
- * @param pattern
- * @param string
- * @param flags
- * @return
- */
-int posix_fnmatch(const char *pattern, const char *string, int flags)
-{
-	// TODO
-	not_implemented();
-}
-
-/** @}
- */
Index: pace/lib/posix/fnmatch.h
===================================================================
--- uspace/lib/posix/fnmatch.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file
- */
-
-#ifndef POSIX_FNMATCH_H_
-#define POSIX_FNMATCH_H_
-
-/* fnmatch flags */
-#undef FNM_PATHNAME
-#undef FNM_NOESCAPE
-#undef FNM_PERIOD
-#define	FNM_PATHNAME  (1 << 0) /* Slash cannot be matched to the wildcard. */
-#define	FNM_NOESCAPE  (1 << 1) /* Disable backslash escaping. */
-#define	FNM_PERIOD    (1 << 2) /* Leading period must be exactly matched. */
-
-/* fnmatch return values */
-#undef FNM_NOMATCH
-#undef FNM_NOSYS
-#define	FNM_NOMATCH          1 /* The string does not match the pattern. */
-#define FNM_NOSYS	      (-1) /* In case fnmatch is not supported. */
-
-extern int posix_fnmatch(const char *pattern, const char *string, int flags);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define fnmatch posix_fnmatch
-#endif
-
-#endif /* POSIX_FNMATCH_H_ */
-
-/** @}
- */
Index: pace/lib/posix/getopt.c
===================================================================
--- uspace/lib/posix/getopt.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file
- */
-
-#define LIBPOSIX_INTERNAL
-
-#include "internal/common.h"
-#include "getopt.h"
-
-/**
- * 
- * @param argc
- * @param argv
- * @param optstring
- * @param longopts
- * @param longindex
- * @return
- */
-int posix_getopt_long(int argc, char * const argv[],
-    const char *optstring, const struct posix_option *longopts, int *longindex)
-{
-	// TODO
-	not_implemented();
-}
-
-/**
- * 
- * @param argc
- * @param argv
- * @param optstring
- * @param longopts
- * @param longindex
- * @return
- */
-int posix_getopt_long_only(int argc, char * const argv[],
-    const char *optstring, const struct posix_option *longopts, int *longindex)
-{
-	// TODO
-	not_implemented();
-}
-
-/** @}
- */
Index: pace/lib/posix/getopt.h
===================================================================
--- uspace/lib/posix/getopt.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * Copyright (c) 2011 Petr Koupy
- * 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 libposix
- * @{
- */
-/** @file
- */
-
-#ifndef POSIX_GETOPT_H_
-#define POSIX_GETOPT_H_
-
-#undef no_argument
-#undef required_argument
-#undef optional_argument
-#define no_argument        0
-#define required_argument  1
-#define optional_argument  2
-
-struct posix_option {
-	const char *name; /* name of the option */
-	int has_arg; /* no_argument / required_argument / optional_argument */
-	int *flag; /* TODO */
-	int val; /* TODO */
-};
-
-extern int posix_getopt_long(int argc, char * const argv[],
-    const char *optstring, const struct posix_option *longopts, int *longindex);
-
-extern int posix_getopt_long_only(int argc, char * const argv[],
-    const char *optstring, const struct posix_option *longopts, int *longindex);
-
-#ifndef LIBPOSIX_INTERNAL
-	#define option posix_option
-	#define posix_getopt_long posix_getopt_long
-	#define getopt_long_only posix_getopt_long_only
-#endif
-
-#endif /* POSIX_GETOPT_H_ */
-
-/** @}
- */
Index: uspace/lib/posix/limits.h
===================================================================
--- uspace/lib/posix/limits.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/posix/limits.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -46,4 +46,7 @@
 #define USHRT_MAX USHORT_MAX
 
+#undef PATH_MAX
+#define PATH_MAX 256
+
 #endif /* POSIX_LIMITS_H_ */
 
Index: uspace/lib/posix/string.h
===================================================================
--- uspace/lib/posix/string.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/posix/string.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -133,5 +133,4 @@
 	#define strerror posix_strerror
 	#define strerror_r posix_strerror_r
-	#define strsignal(i) ((char *) "SIGNonSense: There are no signals in HelenOS.")
 
 	#define strlen posix_strlen
Index: uspace/lib/posix/sys/stat.h
===================================================================
--- uspace/lib/posix/sys/stat.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/posix/sys/stat.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -40,9 +40,4 @@
 #include "types.h"
 #include "../time.h"
-#include <ipc/devmap.h>
-#include <task.h>
-
-typedef devmap_handle_t posix_dev_t;
-typedef task_id_t posix_pid_t;
 
 /* values are the same as on Linux */
@@ -139,6 +134,4 @@
 
 #ifndef LIBPOSIX_INTERNAL
-	#define dev_t posix_dev_t
-	#define pid_t posix_pid_t
 	#define fstat posix_fstat
 	#define lstat posix_lstat
Index: uspace/lib/posix/sys/types.h
===================================================================
--- uspace/lib/posix/sys/types.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/posix/sys/types.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -46,4 +46,6 @@
 typedef unsigned int posix_blksize_t;
 typedef unsigned int posix_blkcnt_t;
+typedef uint64_t posix_pid_t;
+typedef sysarg_t posix_dev_t;
 
 #ifndef LIBPOSIX_INTERNAL
@@ -55,4 +57,6 @@
 	#define blksize_t posix_blksize_t
 	#define blkcnt_t posix_blkcnt_t
+	#define pid_t posix_pid_t
+	#define dev_t posix_dev_t
 #endif
 
Index: uspace/lib/posix/unistd.c
===================================================================
--- uspace/lib/posix/unistd.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/posix/unistd.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -54,4 +54,13 @@
 
 /**
+ * 
+ * @return
+ */
+int posix_getpagesize(void)
+{
+	return getpagesize();
+}
+
+/**
  *
  * @return
Index: uspace/lib/posix/unistd.h
===================================================================
--- uspace/lib/posix/unistd.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/posix/unistd.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -54,4 +54,7 @@
 extern int posix_isatty(int fd);
 
+/* Query Memory Parameters */
+extern int posix_getpagesize(void);
+
 /* Process Identification */
 #define getpid task_get_id
@@ -87,8 +90,34 @@
 extern long posix_sysconf(int name);
 
+/* Path Configuration Parameters */
+enum {
+	_PC_2_SYMLINKS,
+	_PC_ALLOC_SIZE_MIN,
+	_PC_ASYNC_IO,
+	_PC_CHOWN_RESTRICTED,
+	_PC_FILESIZEBITS,
+	_PC_LINK_MAX,
+	_PC_MAX_CANON,
+	_PC_MAX_INPUT,
+	_PC_NAME_MAX,
+	_PC_NO_TRUNC,
+	_PC_PATH_MAX,
+	_PC_PIPE_BUF,
+	_PC_PRIO_IO,
+	_PC_REC_INCR_XFER_SIZE,
+	_PC_REC_MIN_XFER_SIZE,
+	_PC_REC_XFER_ALIGN,
+	_PC_SYMLINK_MAX,
+	_PC_SYNC_IO,
+	_PC_VDISABLE
+};
+
 #ifndef LIBPOSIX_INTERNAL
 	#define environ posix_environ
 
 	#define isatty posix_isatty
+
+	#undef getpagesize
+	#define getpagesize posix_getpagesize
 
 	#define getuid posix_getuid
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usb/include/usb/usb.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -69,4 +69,6 @@
 	USB_DIRECTION_BOTH
 } usb_direction_t;
+
+const char *usb_str_direction(usb_direction_t);
 
 /** USB speeds. */
Index: uspace/lib/usb/src/debug.c
===================================================================
--- uspace/lib/usb/src/debug.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usb/src/debug.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -38,4 +38,5 @@
 #include <stdlib.h>
 #include <stdio.h>
+#include <ddf/log.h>
 #include <usb/debug.h>
 
@@ -67,4 +68,7 @@
 		if (rc > 0) {
 			log_stream = fopen(fname, "w");
+			if (log_stream != NULL)
+				setvbuf(log_stream, NULL, _IOFBF, BUFSIZ);
+			
 			free(fname);
 		}
@@ -193,66 +197,7 @@
 	bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN);
 
-	if (buffer == NULL) {
-		return "(null)";
-	}
-	if (size == 0) {
-		return "(empty)";
-	}
-	if ((dumped_size == 0) || (dumped_size > size)) {
-		dumped_size = size;
-	}
-
-	/* How many bytes are available in the output buffer. */
-	size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
-	char *it = buffer_dump[buffer_dump_index];
-
-	size_t index = 0;
-
-	while (index < size) {
-		/* Determine space before the number. */
-		const char *space_before;
-		if (index == 0) {
-			space_before = "";
-		} else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
-			space_before = "  ";
-		} else {
-			space_before = " ";
-		}
-
-		/*
-		 * Add the byte as a hexadecimal number plus the space.
-		 * We do it into temporary buffer to ensure that always
-		 * the whole byte is printed.
-		 */
-		int val = buffer[index];
-		char current_byte[16];
-		int printed = snprintf(current_byte, 16,
-		    "%s%02x", space_before, val);
-		if (printed < 0) {
-			break;
-		}
-
-		if ((size_t) printed > buffer_remaining_size) {
-			break;
-		}
-
-		/* We can safely add 1, because space for end 0 is reserved. */
-		str_append(it, buffer_remaining_size + 1, current_byte);
-
-		buffer_remaining_size -= printed;
-		/* Point at the terminator 0. */
-		it += printed;
-		index++;
-
-		if (index >= dumped_size) {
-			break;
-		}
-	}
-
-	/* Add how many bytes were not printed. */
-	if (index < size) {
-		snprintf(it, REMAINDER_STR_LEN,
-		    REMAINDER_STR_FMT, size - index);
-	}
+	/* Do the actual dump. */
+	ddf_dump_buffer(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN,
+	    buffer, 1, size, dumped_size);
 
 	/* Next time, use the other buffer. */
Index: uspace/lib/usb/src/hc.c
===================================================================
--- uspace/lib/usb/src/hc.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usb/src/hc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -98,5 +98,5 @@
 		return EBUSY;
 	
-	async_sess_t *sess = devman_device_connect(EXCHANGE_SERIALIZE,
+	async_sess_t *sess = devman_device_connect(EXCHANGE_ATOMIC,
 	    connection->hc_handle, 0);
 	if (!sess)
@@ -177,5 +177,5 @@
 {
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev_handle,
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, dev_handle,
 	    IPC_FLAG_BLOCKING);
 	if (!parent_sess)
@@ -241,5 +241,5 @@
 {
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device_handle,
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,
 	    IPC_FLAG_BLOCKING);
 	if (!parent_sess)
Index: uspace/lib/usb/src/usb.c
===================================================================
--- uspace/lib/usb/src/usb.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usb/src/usb.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -58,4 +58,10 @@
 };
 
+static const char *str_direction[] = {
+	"in",
+	"out",
+	"both"
+};
+
 /** String representation for USB transfer type.
  *
@@ -84,4 +90,17 @@
 }
 
+/** String representation of USB direction.
+ *
+ * @param d The direction.
+ * @return Direction as a string (in English).
+ */
+const char *usb_str_direction(usb_direction_t d)
+{
+	if (d >= ARR_SIZE(str_direction)) {
+		return "invalid";
+	}
+	return str_direction[d];
+}
+
 /** String representation of USB speed.
  *
Index: uspace/lib/usbdev/src/pipes.c
===================================================================
--- uspace/lib/usbdev/src/pipes.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbdev/src/pipes.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -81,5 +81,5 @@
 {
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle,
 	    IPC_FLAG_BLOCKING);
 	if (!parent_sess)
@@ -122,5 +122,5 @@
 	
 	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, dev->handle,
 	    IPC_FLAG_BLOCKING);
 	if (!parent_sess)
Index: uspace/lib/usbhid/include/usb/hid/hiddescriptor.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hiddescriptor.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhid/include/usb/hid/hiddescriptor.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -74,9 +74,9 @@
 		usb_hid_report_path_t *usage_path);
 
-void usb_hid_descriptor_print_list(link_t *head);
+void usb_hid_descriptor_print_list(list_t *list);
 
 void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item);
 
-void usb_hid_free_report_list(link_t *head);
+void usb_hid_free_report_list(list_t *list);
 
 usb_hid_report_item_t *usb_hid_report_item_clone(
Index: uspace/lib/usbhid/include/usb/hid/hidpath.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidpath.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhid/include/usb/hid/hidpath.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -88,6 +88,6 @@
 	uint8_t flags;
 
-	/** Linked list structure*/
-	link_t link;
+	/** Link to usb_hid_report_path_t.items list */
+	link_t rpath_items_link;
 } usb_hid_report_usage_path_t;
 
@@ -98,17 +98,16 @@
  * */
 typedef struct {
-	/** Length of usage path */	
-	int depth;	
+	/** Length of usage path */
+	int depth;
 
 	/** Report id. Zero is reserved and means that report id is not used.
 	 * */
 	uint8_t report_id;
-	
-	/** Linked list structure. */	
-	link_t link; /* list */
 
-	/** Head of the list of usage path items. */
-	link_t head;
+	/** Link to usb_hid_report_path_t.collection_paths list. */
+	link_t cpath_link;
 
+	/** List of usage path items. */
+	list_t items;	/* of usb_hid_report_usage_path_t */
 } usb_hid_report_path_t;
 
Index: uspace/lib/usbhid/include/usb/hid/hidtypes.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidtypes.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhid/include/usb/hid/hidtypes.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -95,9 +95,9 @@
 	int report_count;
 
-	/** Head of linked list of description of reports. */
-	link_t reports;
-
-	/** Head of linked list of all used usage/collection paths. */
-	link_t collection_paths;
+	/** List of description of reports. */
+	list_t reports; /* of usb_hid_report_description_t */
+
+	/** List of all used usage/collection paths. */
+	list_t collection_paths;
 
 	/** Length of list of usage paths. */
@@ -129,9 +129,9 @@
 	size_t item_length;
 	
-	/** Linked list of report items in report */
-	link_t report_items;
-
-	/** Linked list of descriptions. */
-	link_t link;
+	/** List of report items in report */
+	list_t report_items;
+
+	/** Link to usb_hid_report_t.reports list. */
+	link_t reports_link;
 } usb_hid_report_description_t;
 /*---------------------------------------------------------------------------*/
@@ -198,6 +198,6 @@
 	int32_t value;
 
-	/** List to another report items */
-	link_t link;
+	/** Link to usb_hid_report_description_t.report_items list */
+	link_t ritems_link;
 } usb_hid_report_field_t;
 
Index: uspace/lib/usbhid/src/hiddescriptor.c
===================================================================
--- uspace/lib/usbhid/src/hiddescriptor.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhid/src/hiddescriptor.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -88,8 +88,8 @@
  * @retval NULL If some error occurs
  */
-usb_hid_report_path_t *usb_hid_report_path_try_insert(
-		usb_hid_report_t *report, usb_hid_report_path_t *cmp_path) {
-	
-	link_t *path_it = report->collection_paths.prev->next;
+usb_hid_report_path_t *usb_hid_report_path_try_insert(usb_hid_report_t *report,
+    usb_hid_report_path_t *cmp_path)
+{
+	link_t *path_it = report->collection_paths.head.next;
 	usb_hid_report_path_t *path = NULL;
 	
@@ -98,20 +98,20 @@
 	}
 	
-	while(path_it != &report->collection_paths) {
+	while(path_it != &report->collection_paths.head) {
 		path = list_get_instance(path_it, usb_hid_report_path_t,
-				link);
+				cpath_link);
 		
 		if(usb_hid_report_compare_usage_path(path, cmp_path,
 					USB_HID_PATH_COMPARE_STRICT) == EOK){
 			break;
-		}			
+		}
 		path_it = path_it->next;
 	}
-	if(path_it == &report->collection_paths) {
+	if(path_it == &report->collection_paths.head) {
 		path = usb_hid_report_path_clone(cmp_path);
 		if(path == NULL) {
 			return NULL;
 		}
-		list_append(&path->link, &report->collection_paths);					
+		list_append(&path->cpath_link, &report->collection_paths);
 		report->collection_paths_count++;
 
@@ -120,5 +120,5 @@
 	else {
 		return list_get_instance(path_it, usb_hid_report_path_t,
-				link); 
+				cpath_link); 
 	}
 }
@@ -192,5 +192,5 @@
 
 		memset(field, 0, sizeof(usb_hid_report_field_t));
-		list_initialize(&field->link);
+		link_initialize(&field->ritems_link);
 
 		/* fill the attributes */		
@@ -291,13 +291,13 @@
 			}
 
-			list_initialize (&report_des->link);
+			link_initialize (&report_des->reports_link);
 			list_initialize (&report_des->report_items);
 
-			list_append(&report_des->link, &report->reports);
+			list_append(&report_des->reports_link, &report->reports);
 			report->report_count++;
 		}
 
 		/* append this field to the end of founded report list */
-		list_append (&field->link, &report_des->report_items);
+		list_append(&field->ritems_link, &report_des->report_items);
 		
 		/* update the sizes */
@@ -333,10 +333,9 @@
 	}
 
-	link_t *report_it = report->reports.next;
 	usb_hid_report_description_t *report_des = NULL;
 	
-	while(report_it != &report->reports) {
+	list_foreach(report->reports, report_it) {
 		report_des = list_get_instance(report_it,
-				usb_hid_report_description_t, link);
+				usb_hid_report_description_t, reports_link);
 
 		// if report id not set, return the first of the type
@@ -345,6 +344,4 @@
 			return report_des;
 		}
-		
-		report_it = report_it->next;
 	}
 
@@ -377,7 +374,9 @@
 	size_t offset_output=0;
 	size_t offset_feature=0;
-
-	link_t stack;
-	list_initialize(&stack);	
+	
+	link_t *item_link;
+
+	list_t stack;
+	list_initialize(&stack);
 
 	/* parser structure initialization*/
@@ -391,5 +390,5 @@
 	}
 	memset(report_item, 0, sizeof(usb_hid_report_item_t));
-	list_initialize(&(report_item->link));	
+	link_initialize(&(report_item->link));
 
 	/* usage path context initialization */
@@ -493,17 +492,18 @@
 			case USB_HID_REPORT_TAG_POP:
 				// restore current state from stack
-				if(list_empty (&stack)) {
+				item_link = list_first(&stack);
+				if (item_link == NULL) {
 					return EINVAL;
 				}
 				free(report_item);
-						
-				report_item = list_get_instance(stack.next, 
+				
+				report_item = list_get_instance(item_link,
 				    usb_hid_report_item_t, link);
-					
+				
 				usb_hid_report_usage_path_t *tmp_usage_path;
 				tmp_usage_path = list_get_instance(
-				    report_item->usage_path->link.prev, 
-				    usb_hid_report_usage_path_t, link);
-					
+				    report_item->usage_path->cpath_link.prev,
+				    usb_hid_report_usage_path_t, rpath_items_link);
+				
 				usb_hid_report_set_last_item(usage_path, 
 				    USB_HID_TAG_CLASS_GLOBAL, tmp_usage_path->usage_page);
@@ -513,6 +513,5 @@
 
 				usb_hid_report_path_free(report_item->usage_path);
-				list_initialize(&report_item->usage_path->link);
-				list_remove (stack.next);
+				list_remove (item_link);
 					
 				break;
@@ -610,7 +609,7 @@
 
 		/* store collection atributes */
-		path_item = list_get_instance(usage_path->head.prev, 
-			usb_hid_report_usage_path_t, link);
-		path_item->flags = *data;	
+		path_item = list_get_instance(list_first(&usage_path->items),
+			usb_hid_report_usage_path_t, rpath_items_link);
+		path_item->flags = *data;
 			
 		/* set last item */
@@ -901,35 +900,32 @@
  * @return void
  */
-void usb_hid_descriptor_print_list(link_t *head)
+void usb_hid_descriptor_print_list(list_t *list)
 {
 	usb_hid_report_field_t *report_item;
-	link_t *item;
-
-
-	if(head == NULL || list_empty(head)) {
+
+	if(list == NULL || list_empty(list)) {
 	    usb_log_debug("\tempty\n");
 	    return;
 	}
-        
-	for(item = head->next; item != head; item = item->next) {
-                
-		report_item = list_get_instance(item, usb_hid_report_field_t, 
-				link);
+
+        list_foreach(*list, item) {
+		report_item = list_get_instance(item, usb_hid_report_field_t,
+				ritems_link);
 
 		usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
 		usb_log_debug("\t\tSIZE: %zu\n", report_item->size);
-		usb_log_debug("\t\tLOGMIN: %d\n", 
+		usb_log_debug("\t\tLOGMIN: %d\n",
 			report_item->logical_minimum);
-		usb_log_debug("\t\tLOGMAX: %d\n", 
-			report_item->logical_maximum);		
-		usb_log_debug("\t\tPHYMIN: %d\n", 
-			report_item->physical_minimum);		
-		usb_log_debug("\t\tPHYMAX: %d\n", 
-			report_item->physical_maximum);				
-		usb_log_debug("\t\ttUSAGEMIN: %X\n", 
+		usb_log_debug("\t\tLOGMAX: %d\n",
+			report_item->logical_maximum);
+		usb_log_debug("\t\tPHYMIN: %d\n",
+			report_item->physical_minimum);
+		usb_log_debug("\t\tPHYMAX: %d\n",
+			report_item->physical_maximum);
+		usb_log_debug("\t\ttUSAGEMIN: %X\n",
 			report_item->usage_minimum);
 		usb_log_debug("\t\tUSAGEMAX: %X\n",
 			       report_item->usage_maximum);
-		usb_log_debug("\t\tUSAGES COUNT: %zu\n", 
+		usb_log_debug("\t\tUSAGES COUNT: %zu\n",
 			report_item->usages_count);
 
@@ -937,8 +933,8 @@
 		usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
 		usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
-		
+
 		usb_hid_print_usage_path(report_item->collection_path);
 
-		usb_log_debug("\n");		
+		usb_log_debug("\n");
 
 	}
@@ -959,22 +955,19 @@
 	}
 
-	link_t *report_it = report->reports.next;
 	usb_hid_report_description_t *report_des;
 
-	while(report_it != &report->reports) {
-		report_des = list_get_instance(report_it, 
-			usb_hid_report_description_t, link);
+	list_foreach(report->reports, report_it) {
+		report_des = list_get_instance(report_it,
+			usb_hid_report_description_t, reports_link);
 		usb_log_debug("Report ID: %d\n", report_des->report_id);
 		usb_log_debug("\tType: %d\n", report_des->type);
-		usb_log_debug("\tLength: %zu\n", report_des->bit_length);		
+		usb_log_debug("\tLength: %zu\n", report_des->bit_length);
 		usb_log_debug("\tB Size: %zu\n",
-			usb_hid_report_byte_size(report, 
-				report_des->report_id, 
+			usb_hid_report_byte_size(report,
+				report_des->report_id,
 				report_des->type));
-		usb_log_debug("\tItems: %zu\n", report_des->item_length);		
+		usb_log_debug("\tItems: %zu\n", report_des->item_length);
 
 		usb_hid_descriptor_print_list(&report_des->report_items);
-
-		report_it = report_it->next;
 	}
 }
@@ -984,25 +977,25 @@
  * Releases whole linked list of report items
  *
- * @param head Head of list of report descriptor items (usb_hid_report_item_t)
+ * @param list List of report descriptor items (usb_hid_report_item_t)
  * @return void
  */
-void usb_hid_free_report_list(link_t *head)
+void usb_hid_free_report_list(list_t *list)
 {
-	return; 
-	
-	usb_hid_report_item_t *report_item;
+	return; /* XXX What's this? */
+	
+/*	usb_hid_report_item_t *report_item;
 	link_t *next;
 	
-	if(head == NULL || list_empty(head)) {		
+	if(list == NULL || list_empty(list)) {
 	    return;
 	}
 	
-	next = head->next;
-	while(next != head) {
-	
-	    report_item = list_get_instance(next, usb_hid_report_item_t, link);
+	next = list->head.next;
+	while (next != &list->head) {
+		report_item = list_get_instance(next, usb_hid_report_item_t,
+		    rpath_items_link);
 
 		while(!list_empty(&report_item->usage_path->link)) {
-		    usb_hid_report_remove_last_item(report_item->usage_path);
+			usb_hid_report_remove_last_item(report_item->usage_path);
 		}
 
@@ -1014,5 +1007,5 @@
 	
 	return;
-	
+	*/
 }
 /*---------------------------------------------------------------------------*/
@@ -1030,10 +1023,13 @@
 
 	// free collection paths
+	link_t *path_link;
 	usb_hid_report_path_t *path;
 	while(!list_empty(&report->collection_paths)) {
-		path = list_get_instance(report->collection_paths.next, 
-				usb_hid_report_path_t, link);
-
-		usb_hid_report_path_free(path);		
+		path_link = list_first(&report->collection_paths);
+		path = list_get_instance(path_link,
+		    usb_hid_report_path_t, cpath_link);
+
+		list_remove(path_link);
+		usb_hid_report_path_free(path);
 	}
 	
@@ -1042,15 +1038,15 @@
 	usb_hid_report_field_t *field;
 	while(!list_empty(&report->reports)) {
-		report_des = list_get_instance(report->reports.next, 
-				usb_hid_report_description_t, link);
-
-		list_remove(&report_des->link);
+		report_des = list_get_instance(list_first(&report->reports),
+				usb_hid_report_description_t, reports_link);
+
+		list_remove(&report_des->reports_link);
 		
 		while(!list_empty(&report_des->report_items)) {
 			field = list_get_instance(
-				report_des->report_items.next, 
-				usb_hid_report_field_t, link);
-
-			list_remove(&field->link);
+			    list_first(&report_des->report_items),
+			    usb_hid_report_field_t, ritems_link);
+
+			list_remove(&field->ritems_link);
 
 			free(field);
Index: uspace/lib/usbhid/src/hidparser.c
===================================================================
--- uspace/lib/usbhid/src/hidparser.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhid/src/hidparser.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -135,5 +135,4 @@
 	size_t size, uint8_t *report_id)
 {
-	link_t *list_item;
 	usb_hid_report_field_t *item;
 
@@ -161,9 +160,7 @@
 
 	/* read data */
-	list_item = report_des->report_items.next;	   
-	while(list_item != &(report_des->report_items)) {
-
+	list_foreach(report_des->report_items, list_item) {
 		item = list_get_instance(list_item, usb_hid_report_field_t, 
-				link);
+				ritems_link);
 
 		if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
@@ -200,5 +197,4 @@
 			}			
 		}
-		list_item = list_item->next;
 	}
 	
@@ -310,16 +306,14 @@
 	}
 
-	link_t *report_it = report->reports.next;
 	usb_hid_report_description_t *report_des = NULL;
-	while(report_it != &report->reports) {
-		report_des = list_get_instance(report_it, 
-			usb_hid_report_description_t, link);
+
+	list_foreach(report->reports, report_it) {
+		report_des = list_get_instance(report_it,
+			usb_hid_report_description_t, reports_link);
 		
-		if((report_des->report_id == report_id) && 
+		if((report_des->report_id == report_id) &&
 			(report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
 			break;
 		}
-
-		report_it = report_it->next;
 	}
 
@@ -362,5 +356,4 @@
 	uint8_t report_id, uint8_t *buffer, size_t size)
 {
-	link_t *item;	
 	int32_t value=0;
 	int offset;
@@ -384,8 +377,9 @@
 	}
 
-	usb_hid_report_field_t *report_item;	
-	item = report_des->report_items.next;	
-	while(item != &report_des->report_items) {
-		report_item = list_get_instance(item, usb_hid_report_field_t, link);
+	usb_hid_report_field_t *report_item;
+
+	list_foreach(report_des->report_items, item) {
+		report_item = list_get_instance(item, usb_hid_report_field_t,
+		    ritems_link);
 
 		value = usb_hid_translate_data_reverse(report_item, 
@@ -449,6 +443,4 @@
 		// reset value
 		report_item->value = 0;
-		
-		item = item->next;
 	}
 	
@@ -550,13 +542,13 @@
 
 	if(field == NULL){
-		field_it = report_des->report_items.next;
-	}
-	else {
-		field_it = field->link.next;
-	}
-
-	while(field_it != &report_des->report_items) {
+		field_it = report_des->report_items.head.next;
+	}
+	else {
+		field_it = field->ritems_link.next;
+	}
+
+	while(field_it != &report_des->report_items.head) {
 		field = list_get_instance(field_it, usb_hid_report_field_t, 
-			link);
+			ritems_link);
 
 		if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
@@ -611,14 +603,14 @@
 		}
 		else {
-			report_it = report_des->link.next;
+			report_it = report_des->reports_link.next;
 		}	
 	}
 	else {
-		report_it = report->reports.next;
-	}
-
-	while(report_it != &report->reports) {
+		report_it = report->reports.head.next;
+	}
+
+	while(report_it != &report->reports.head) {
 		report_des = list_get_instance(report_it, 
-			usb_hid_report_description_t, link);
+			usb_hid_report_description_t, reports_link);
 
 		if(report_des->type == type){
Index: uspace/lib/usbhid/src/hidpath.c
===================================================================
--- uspace/lib/usbhid/src/hidpath.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhid/src/hidpath.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -81,5 +81,5 @@
 		return ENOMEM;
 	}
-	list_initialize(&item->link);
+	link_initialize(&item->rpath_items_link);
 
 	item->usage = usage;
@@ -87,5 +87,5 @@
 	item->flags = 0;
 	
-	list_append (&item->link, &usage_path->head);
+	list_append (&item->rpath_items_link, &usage_path->items);
 	usage_path->depth++;
 	return EOK;
@@ -100,10 +100,12 @@
 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
 {
+	link_t *item_link;
 	usb_hid_report_usage_path_t *item;
 	
-	if(!list_empty(&usage_path->head)){
-		item = list_get_instance(usage_path->head.prev, 
-		                         usb_hid_report_usage_path_t, link);		
-		list_remove(usage_path->head.prev);
+	if(!list_empty(&usage_path->items)){
+		item_link = list_last(&usage_path->items);
+		item = list_get_instance(item_link,
+		    usb_hid_report_usage_path_t, rpath_items_link);
+		list_remove(item_link);
 		usage_path->depth--;
 		free(item);
@@ -122,7 +124,7 @@
 	usb_hid_report_usage_path_t *item;
 	
-	if(!list_empty(&usage_path->head)){	
-		item = list_get_instance(usage_path->head.prev, 
-			usb_hid_report_usage_path_t, link);
+	if(!list_empty(&usage_path->items)){
+		item = list_get_instance(list_last(&usage_path->items),
+			usb_hid_report_usage_path_t, rpath_items_link);
 
 		memset(item, 0, sizeof(usb_hid_report_usage_path_t));
@@ -145,7 +147,7 @@
 	usb_hid_report_usage_path_t *item;
 	
-	if(!list_empty(&usage_path->head)){	
-		item = list_get_instance(usage_path->head.prev, 
-		                         usb_hid_report_usage_path_t, link);
+	if(!list_empty(&usage_path->items)){
+		item = list_get_instance(list_last(&usage_path->items),
+		     usb_hid_report_usage_path_t, rpath_items_link);
 
 		switch(tag) {
@@ -173,16 +175,13 @@
 	usb_log_debug("\tLENGTH: %d\n", path->depth);
 
-	link_t *item = path->head.next;
 	usb_hid_report_usage_path_t *path_item;
-	while(item != &path->head) {
-
-		path_item = list_get_instance(item, usb_hid_report_usage_path_t, 
-			link);
+
+	list_foreach(path->items, item) {
+		path_item = list_get_instance(item, usb_hid_report_usage_path_t,
+			rpath_items_link);
 
 		usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
 		usb_log_debug("\tUSAGE: %X\n", path_item->usage);
-		usb_log_debug("\tFLAGS: %d\n", path_item->flags);		
-		
-       	item = item->next;
+		usb_log_debug("\tFLAGS: %d\n", path_item->flags);
 	}
 }
@@ -233,14 +232,13 @@
 		}
 
-		report_link = report_path->head.next;
-		path_link = path->head.next;
-		path_item = list_get_instance(path_link, 
-			usb_hid_report_usage_path_t, link);
-
-		while(report_link != &report_path->head) {
-			report_item = list_get_instance(report_link, 
-				usb_hid_report_usage_path_t, link);
+		path_link = list_first(&path->items);
+		path_item = list_get_instance(path_link,
+			usb_hid_report_usage_path_t, rpath_items_link);
+
+		list_foreach(report_path->items, report_link) {
+			report_item = list_get_instance(report_link,
+				usb_hid_report_usage_path_t, rpath_items_link);
 				
-			if(USB_HID_SAME_USAGE_PAGE(report_item->usage_page, 
+			if(USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
 				path_item->usage_page)){
 					
@@ -257,6 +255,4 @@
 				}
 			}
-
-			report_link = report_link->next;
 		}
 
@@ -273,15 +269,15 @@
 	case USB_HID_PATH_COMPARE_BEGIN:
 	
-		report_link = report_path->head.next;
-		path_link = path->head.next;
+		report_link = report_path->items.head.next;
+		path_link = path->items.head.next;
 			
-		while((report_link != &report_path->head) && 
-		      (path_link != &path->head)) {
+		while((report_link != &report_path->items.head) && 
+		      (path_link != &path->items.head)) {
 					  
 			report_item = list_get_instance(report_link, 
-				usb_hid_report_usage_path_t, link);
+				usb_hid_report_usage_path_t, rpath_items_link);
 					  
 			path_item = list_get_instance(path_link,
-       				usb_hid_report_usage_path_t, link);
+       				usb_hid_report_usage_path_t, rpath_items_link);
 
 			if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page, 
@@ -297,10 +293,10 @@
 			}
 			
-				}
+		}
 
 		if((((flags & USB_HID_PATH_COMPARE_BEGIN) != 0) && 
-			(path_link == &path->head)) || 
-		   ((report_link == &report_path->head) && 
-			(path_link == &path->head))) {
+			(path_link == &path->items.head)) || 
+		   ((report_link == &report_path->items.head) && 
+			(path_link == &path->items.head))) {
 				
 			return EOK;
@@ -314,19 +310,19 @@
 	case USB_HID_PATH_COMPARE_END:
 
-		report_link = report_path->head.prev;
-		path_link = path->head.prev;
-
-		if(list_empty(&path->head)){
+		report_link = report_path->items.head.prev;
+		path_link = path->items.head.prev;
+
+		if(list_empty(&path->items)){
 			return EOK;
 		}
 			
-		while((report_link != &report_path->head) && 
-		      (path_link != &path->head)) {
+		while((report_link != &report_path->items.head) && 
+		      (path_link != &path->items.head)) {
 						  
-			report_item = list_get_instance(report_link, 
-				usb_hid_report_usage_path_t, link);
+			report_item = list_get_instance(report_link,
+				usb_hid_report_usage_path_t, rpath_items_link);
 
 			path_item = list_get_instance(path_link, 
-				usb_hid_report_usage_path_t, link);		
+				usb_hid_report_usage_path_t, rpath_items_link);
 						  
 			if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page, 
@@ -343,5 +339,5 @@
 		}
 
-		if(path_link == &path->head) {
+		if(path_link == &path->items.head) {
 			return EOK;
 		}
@@ -373,6 +369,6 @@
 		path->depth = 0;
 		path->report_id = 0;
-		list_initialize(&path->link);
-		list_initialize(&path->head);
+		link_initialize(&path->cpath_link);
+		list_initialize(&path->items);
 		return path;
 	}
@@ -388,9 +384,9 @@
 void usb_hid_report_path_free(usb_hid_report_path_t *path)
 {
-	while(!list_empty(&path->head)){
+	while(!list_empty(&path->items)){
 		usb_hid_report_remove_last_item(path);
 	}
 
-	list_remove(&path->link);
+	assert_link_not_used(&path->cpath_link);
 	free(path);
 }
@@ -406,5 +402,4 @@
 	usb_hid_report_path_t *usage_path)
 {
-	link_t *path_link;
 	usb_hid_report_usage_path_t *path_item;
 	usb_hid_report_usage_path_t *new_path_item;
@@ -417,12 +412,11 @@
 	new_usage_path->report_id = usage_path->report_id;
 	
-	if(list_empty(&usage_path->head)){
+	if(list_empty(&usage_path->items)){
 		return new_usage_path;
 	}
 
-	path_link = usage_path->head.next;
-	while(path_link != &usage_path->head) {
-		path_item = list_get_instance(path_link, 
-			usb_hid_report_usage_path_t, link);
+	list_foreach(usage_path->items, path_link) {
+		path_item = list_get_instance(path_link,
+			usb_hid_report_usage_path_t, rpath_items_link);
 
 		new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
@@ -431,13 +425,12 @@
 		}
 		
-		list_initialize (&new_path_item->link);		
+		link_initialize(&new_path_item->rpath_items_link);
 		new_path_item->usage_page = path_item->usage_page;
 		new_path_item->usage = path_item->usage;		
 		new_path_item->flags = path_item->flags;		
 		
-		list_append(&new_path_item->link, &new_usage_path->head);
+		list_append(&new_path_item->rpath_items_link,
+		    &new_usage_path->items);
 		new_usage_path->depth++;
-
-		path_link = path_link->next;
 	}
 
Index: uspace/lib/usbhid/src/hidreq.c
===================================================================
--- uspace/lib/usbhid/src/hidreq.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhid/src/hidreq.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -82,5 +82,5 @@
 	value |= (type << 8);
 
-	usb_log_debug("Sending Set_Report request to the device.\n");
+	usb_log_debug("Sending Set Report request to the device.\n");
 	
 	rc = usb_control_request_set(ctrl_pipe, 
@@ -89,6 +89,6 @@
 
 	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
+		usb_log_warning("Error sending Set Report request to the "
+		    "device: %s.\n", str_error(rc));
 		return rc;
 	}
@@ -129,5 +129,5 @@
 	int rc;
 
-	usb_log_debug("Sending Set_Protocol request to the device ("
+	usb_log_debug("Sending Set Protocol request to the device ("
 	    "protocol: %d, iface: %d).\n", protocol, iface_no);
 	
@@ -137,6 +137,6 @@
 
 	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
+		usb_log_warning("Error sending Set Protocol request to the "
+		    "device: %s.\n", str_error(rc));
 		return rc;
 	}
@@ -177,5 +177,5 @@
 	int rc;
 
-	usb_log_debug("Sending Set_Idle request to the device ("
+	usb_log_debug("Sending Set Idle request to the device ("
 	    "duration: %u, iface: %d).\n", duration, iface_no);
 	
@@ -187,5 +187,5 @@
 
 	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
+		usb_log_warning("Error sending Set Idle request to the device: "
 		    "%s.\n", str_error(rc));
 		return rc;
@@ -235,5 +235,5 @@
 	value |= (type << 8);
 	
-	usb_log_debug("Sending Get_Report request to the device.\n");
+	usb_log_debug("Sending Get Report request to the device.\n");
 	
 	rc = usb_control_request_get(ctrl_pipe, 
@@ -243,5 +243,5 @@
 
 	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
+		usb_log_warning("Error sending Get Report request to the device: "
 		    "%s.\n", str_error(rc));
 		return rc;
@@ -283,5 +283,5 @@
 	int rc;	
 
-	usb_log_debug("Sending Get_Protocol request to the device ("
+	usb_log_debug("Sending Get Protocol request to the device ("
 	    "iface: %d).\n", iface_no);
 	
@@ -294,6 +294,6 @@
 
 	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
-		    "%s.\n", str_error(rc));
+		usb_log_warning("Error sending Get Protocol request to the "
+		    "device: %s.\n", str_error(rc));
 		return rc;
 	}
@@ -344,5 +344,5 @@
 	int rc;
 
-	usb_log_debug("Sending Get_Idle request to the device ("
+	usb_log_debug("Sending Get Idle request to the device ("
 	    "iface: %d).\n", iface_no);
 	
@@ -357,5 +357,5 @@
 
 	if (rc != EOK) {
-		usb_log_warning("Error sending output report to the keyboard: "
+		usb_log_warning("Error sending Get Idle request to the device: "
 		    "%s.\n", str_error(rc));
 		return rc;
Index: uspace/lib/usbhost/include/usb/host/batch.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/batch.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhost/include/usb/host/batch.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -61,4 +61,18 @@
 };
 
+/** Printf formatting string for dumping usb_transfer_batch_t. */
+#define USB_TRANSFER_BATCH_FMT "[%d:%d %s %s-%s %zuB/%zu]"
+
+/** Printf arguments for dumping usb_transfer_batch_t.
+ * @param batch USB transfer batch to be dumped.
+ */
+#define USB_TRANSFER_BATCH_ARGS(batch) \
+	(batch).ep->address, (batch).ep->endpoint, \
+	usb_str_speed((batch).ep->speed), \
+	usb_str_transfer_type_short((batch).ep->transfer_type), \
+	usb_str_direction((batch).ep->direction), \
+	(batch).buffer_size, (batch).ep->max_packet_size
+
+
 void usb_transfer_batch_init(
     usb_transfer_batch_t *instance,
Index: uspace/lib/usbhost/src/batch.c
===================================================================
--- uspace/lib/usbhost/src/batch.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbhost/src/batch.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -128,10 +128,7 @@
 	memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
 
-	usb_log_debug("Batch(%p) done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
-	    instance, instance->ep->address, instance->ep->endpoint,
-	    usb_str_speed(instance->ep->speed),
-	    usb_str_transfer_type_short(instance->ep->transfer_type),
-	    instance->transfered_size, str_error(instance->error),
-	    instance->error);
+	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
+	    instance, USB_TRANSFER_BATCH_ARGS(*instance),
+	    instance->transfered_size, str_error(instance->error));
 
 	instance->callback_in(instance->fun, instance->error,
@@ -148,9 +145,7 @@
 	assert(instance->callback_out);
 
-	usb_log_debug("Batch(%p) done (T%d.%d, %s %s out): %s (%d).\n",
-	    instance, instance->ep->address, instance->ep->endpoint,
-	    usb_str_speed(instance->ep->speed),
-	    usb_str_transfer_type_short(instance->ep->transfer_type),
-	    str_error(instance->error), instance->error);
+	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n",
+	    instance, USB_TRANSFER_BATCH_ARGS(*instance),
+	    str_error(instance->error));
 
 	instance->callback_out(instance->fun,
@@ -165,5 +160,6 @@
 {
 	assert(instance);
-	usb_log_debug("Batch(%p) disposing.\n", instance);
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
+	    instance, USB_TRANSFER_BATCH_ARGS(*instance));
 	if (instance->private_data) {
 		assert(instance->private_data_dtor);
Index: uspace/lib/usbvirt/src/device.c
===================================================================
--- uspace/lib/usbvirt/src/device.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/lib/usbvirt/src/device.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -49,7 +49,7 @@
 /** Main IPC call handling from virtual host controller.
  *
- * @param iid		Caller identification
- * @param icall		Initial incoming call
- * @param arg		Local argument
+ * @param iid   Caller identification
+ * @param icall Initial incoming call
+ * @param arg   Local argument
  */
 static void callback_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/devman/devman.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -466,6 +466,5 @@
 	fibril_mutex_lock(&drivers_list->drivers_mutex);
 	
-	link_t *link = drivers_list->drivers.next;
-	while (link != &drivers_list->drivers) {
+	list_foreach(drivers_list->drivers, link) {
 		drv = list_get_instance(link, driver_t, drivers);
 		score = get_match_score(drv, node);
@@ -474,5 +473,4 @@
 			best_drv = drv;
 		}
-		link = link->next;
 	}
 	
@@ -536,10 +534,8 @@
 	driver_t *res = NULL;
 	driver_t *drv = NULL;
-	link_t *link;
 	
 	fibril_mutex_lock(&drv_list->drivers_mutex);
 	
-	link = drv_list->drivers.next;
-	while (link != &drv_list->drivers) {
+	list_foreach(drv_list->drivers, link) {
 		drv = list_get_instance(link, driver_t, drivers);
 		if (str_cmp(drv->name, drv_name) == 0) {
@@ -547,6 +543,4 @@
 			break;
 		}
-
-		link = link->next;
 	}
 	
@@ -584,6 +578,6 @@
 	 * that has not been passed to the driver.
 	 */
-	link = driver->devices.next;
-	while (link != &driver->devices) {
+	link = driver->devices.head.next;
+	while (link != &driver->devices.head) {
 		dev = list_get_instance(link, dev_node_t, driver_devices);
 		if (dev->passed_to_driver) {
@@ -622,5 +616,5 @@
 		 * Restart the cycle to go through all devices again.
 		 */
-		link = driver->devices.next;
+		link = driver->devices.head.next;
 	}
 
@@ -1187,9 +1181,6 @@
 
 	fun_node_t *fun;
-	link_t *link;
-
-	for (link = dev->functions.next;
-	    link != &dev->functions;
-	    link = link->next) {
+
+	list_foreach(dev->functions, link) {
 		fun = list_get_instance(link, fun_node_t, dev_functions);
 
@@ -1385,12 +1376,10 @@
 {
 	dev_class_t *cl;
-	link_t *link = class_list->classes.next;
-	
-	while (link != &class_list->classes) {
+	
+	list_foreach(class_list->classes, link) {
 		cl = list_get_instance(link, dev_class_t, link);
 		if (str_cmp(cl->name, class_name) == 0) {
 			return cl;
 		}
-		link = link->next;
 	}
 	
@@ -1408,8 +1397,5 @@
 	assert(dev_name != NULL);
 
-	link_t *link;
-	for (link = dev_class->devices.next;
-	    link != &dev_class->devices;
-	    link = link->next) {
+	list_foreach(dev_class->devices, link) {
 		dev_class_info_t *dev = list_get_instance(link,
 		    dev_class_info_t, link);
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/devman/devman.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -96,6 +96,6 @@
 	/** List of device ids for device-to-driver matching. */
 	match_id_list_t match_ids;
-	/** Pointer to the linked list of devices controlled by this driver. */
-	link_t devices;
+	/** List of devices controlled by this driver. */
+	list_t devices;
 	
 	/**
@@ -108,5 +108,5 @@
 typedef struct driver_list {
 	/** List of drivers */
-	link_t drivers;
+	list_t drivers;
 	/** Fibril mutex for list of drivers. */
 	fibril_mutex_t drivers_mutex;
@@ -130,5 +130,5 @@
 	
 	/** List of device functions. */
-	link_t functions;
+	list_t functions;
 	/** Driver of this device. */
 	driver_t *drv;
@@ -170,6 +170,6 @@
 	match_id_list_t match_ids;
 	
-	/** The list of device classes to which this device function belongs. */
-	link_t classes;
+	/** List of device classes to which this device function belongs. */
+	list_t classes;
 	/** Devmap handle if the device function is registered by devmap. */
 	devmap_handle_t devmap_handle;
@@ -228,5 +228,5 @@
 	 * this class.
 	 */
-	link_t devices;
+	list_t devices;
 	
 	/**
@@ -280,5 +280,5 @@
 typedef struct class_list {
 	/** List of classes. */
-	link_t classes;
+	list_t classes;
 	
 	/**
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/devman/match.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -59,9 +59,11 @@
 int get_match_score(driver_t *drv, dev_node_t *dev)
 {
-	link_t *drv_head = &drv->match_ids.ids;
-	link_t *dev_head = &dev->pfun->match_ids.ids;
+	link_t *drv_head = &drv->match_ids.ids.head;
+	link_t *dev_head = &dev->pfun->match_ids.ids.head;
 	
-	if (list_empty(drv_head) || list_empty(dev_head))
+	if (list_empty(&drv->match_ids.ids) ||
+	    list_empty(&dev->pfun->match_ids.ids)) {
 		return 0;
+	}
 	
 	/*
@@ -70,5 +72,5 @@
 	int highest_score = 0;
 	
-	link_t *drv_link = drv->match_ids.ids.next;
+	link_t *drv_link = drv->match_ids.ids.head.next;
 	while (drv_link != drv_head) {
 		link_t *dev_link = dev_head->next;
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/devmap/devmap.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -57,9 +57,9 @@
  */
 typedef struct {
-	/** Pointers to previous and next drivers in linked list */
+	/** Link to drivers_list */
 	link_t drivers;
 	
-	/** Pointer to the linked list of devices controlled by this driver */
-	link_t devices;
+	/** List of devices controlled by this driver */
+	list_t devices;
 	
 	/** Session asociated with this driver */
@@ -77,5 +77,5 @@
  */
 typedef struct {
-	/** Pointer to the previous and next device in the list of all namespaces */
+	/** Link to namespaces_list */
 	link_t namespaces;
 	
@@ -94,8 +94,7 @@
  */
 typedef struct {
-	/** Pointer to the previous and next device in the list of all devices */
+	/** Link to global list of devices (devices_list) */
 	link_t devices;
-	/** Pointer to the previous and next device in the list of devices
-	    owned by one driver */
+	/** Link to driver list of devices (devmap_driver_t.devices) */
 	link_t driver_devices;
 	/** Unique device identifier */
@@ -225,9 +224,7 @@
 static devmap_namespace_t *devmap_namespace_find_name(const char *name)
 {
-	link_t *item;
-	
 	assert(fibril_mutex_is_locked(&devices_list_mutex));
 	
-	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
+	list_foreach(namespaces_list, item) {
 		devmap_namespace_t *namespace =
 		    list_get_instance(item, devmap_namespace_t, namespaces);
@@ -246,9 +243,7 @@
 static devmap_namespace_t *devmap_namespace_find_handle(devmap_handle_t handle)
 {
-	link_t *item;
-	
 	assert(fibril_mutex_is_locked(&devices_list_mutex));
 	
-	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
+	list_foreach(namespaces_list, item) {
 		devmap_namespace_t *namespace =
 		    list_get_instance(item, devmap_namespace_t, namespaces);
@@ -264,9 +259,7 @@
     const char *name)
 {
-	link_t *item;
-	
 	assert(fibril_mutex_is_locked(&devices_list_mutex));
 	
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
+	list_foreach(devices_list, item) {
 		devmap_device_t *device =
 		    list_get_instance(item, devmap_device_t, devices);
@@ -286,9 +279,7 @@
 static devmap_device_t *devmap_device_find_handle(devmap_handle_t handle)
 {
-	link_t *item;
-	
 	assert(fibril_mutex_is_locked(&devices_list_mutex));
 	
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
+	list_foreach(devices_list, item) {
 		devmap_device_t *device =
 		    list_get_instance(item, devmap_device_t, devices);
@@ -473,7 +464,8 @@
 	fibril_mutex_lock(&driver->devices_mutex);
 	
-	while (!list_empty(&(driver->devices))) {
-		devmap_device_t *device = list_get_instance(driver->devices.next,
-		    devmap_device_t, driver_devices);
+	while (!list_empty(&driver->devices)) {
+		devmap_device_t *device = list_get_instance(
+		    list_first(&driver->devices), devmap_device_t,
+		    driver_devices);
 		devmap_device_unregister_core(device);
 	}
@@ -815,8 +807,6 @@
 	}
 	
-	link_t *item;
 	size_t pos = 0;
-	for (item = namespaces_list.next; item != &namespaces_list;
-	    item = item->next) {
+	list_foreach(namespaces_list, item) {
 		devmap_namespace_t *namespace =
 		    list_get_instance(item, devmap_namespace_t, namespaces);
@@ -881,7 +871,6 @@
 	}
 	
-	link_t *item;
 	size_t pos = 0;
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
+	list_foreach(devices_list, item) {
 		devmap_device_t *device =
 		    list_get_instance(item, devmap_device_t, devices);
Index: uspace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -187,5 +187,4 @@
 {
 	EXT2FS_DBG("(%" PRIun ", -)", devmap_handle);
-	link_t *link;
 	ext2fs_instance_t *tmp;
 	
@@ -198,5 +197,5 @@
 	}
 
-	for (link = instance_list.next; link != &instance_list; link = link->next) {
+	list_foreach(instance_list, link) {
 		tmp = list_get_instance(link, ext2fs_instance_t, link);
 		
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/fs/fat/fat_idx.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -59,13 +59,13 @@
 typedef struct {
 	link_t		link;
-	devmap_handle_t	devmap_handle;
+	devmap_handle_t devmap_handle;
 
 	/** Next unassigned index. */
-	fs_index_t	next;
+	fs_index_t next;
 	/** Number of remaining unassigned indices. */
-	uint64_t	remaining;
+	uint64_t remaining;
 
 	/** Sorted list of intervals of freed indices. */
-	link_t		freed_head;
+	list_t freed_list;
 } unused_t;
 
@@ -74,5 +74,5 @@
 
 /** List of unused structures. */
-static LIST_INITIALIZE(unused_head);
+static LIST_INITIALIZE(unused_list);
 
 static void unused_initialize(unused_t *u, devmap_handle_t devmap_handle)
@@ -82,5 +82,5 @@
 	u->next = 0;
 	u->remaining = ((uint64_t)((fs_index_t)-1)) + 1;
-	list_initialize(&u->freed_head);
+	list_initialize(&u->freed_list);
 }
 
@@ -88,13 +88,14 @@
 {
 	unused_t *u;
-	link_t *l;
 
 	if (lock)
 		fibril_mutex_lock(&unused_lock);
-	for (l = unused_head.next; l != &unused_head; l = l->next) {
+
+	list_foreach(unused_list, l) {
 		u = list_get_instance(l, unused_t, link);
 		if (u->devmap_handle == devmap_handle) 
 			return u;
 	}
+	
 	if (lock)
 		fibril_mutex_unlock(&unused_lock);
@@ -249,5 +250,5 @@
 		return false;	
 
-	if (list_empty(&u->freed_head)) {
+	if (list_empty(&u->freed_list)) {
 		if (u->remaining) { 
 			/*
@@ -262,6 +263,6 @@
 	} else {
 		/* There are some freed indices which we can reuse. */
-		freed_t *f = list_get_instance(u->freed_head.next, freed_t,
-		    link);
+		freed_t *f = list_get_instance(list_first(&u->freed_list),
+		    freed_t, link);
 		*index = f->first;
 		if (f->first++ == f->last) {
@@ -320,10 +321,10 @@
 		link_t *lnk;
 		freed_t *n;
-		for (lnk = u->freed_head.next; lnk != &u->freed_head;
+		for (lnk = u->freed_list.head.next; lnk != &u->freed_list.head;
 		    lnk = lnk->next) {
 			freed_t *f = list_get_instance(lnk, freed_t, link);
 			if (f->first == index + 1) {
 				f->first--;
-				if (lnk->prev != &u->freed_head)
+				if (lnk->prev != &u->freed_list.head)
 					try_coalesce_intervals(lnk->prev, lnk,
 					    lnk);
@@ -333,5 +334,5 @@
 			if (f->last == index - 1) {
 				f->last++;
-				if (lnk->next != &u->freed_head)
+				if (lnk->next != &u->freed_list.head)
 					try_coalesce_intervals(lnk, lnk->next,
 					    lnk);
@@ -359,5 +360,5 @@
 		n->first = index;
 		n->last = index;
-		list_append(&n->link, &u->freed_head);
+		list_append(&n->link, &u->freed_list);
 	}
 	fibril_mutex_unlock(&unused_lock);
@@ -558,5 +559,5 @@
 	fibril_mutex_lock(&unused_lock);
 	if (!unused_find(devmap_handle, false)) {
-		list_append(&u->link, &unused_head);
+		list_append(&u->link, &unused_list);
 	} else {
 		free(u);
@@ -594,7 +595,7 @@
 	fibril_mutex_unlock(&unused_lock);
 
-	while (!list_empty(&u->freed_head)) {
+	while (!list_empty(&u->freed_list)) {
 		freed_t *f;
-		f = list_get_instance(u->freed_head.next, freed_t, link);
+		f = list_get_instance(list_first(&u->freed_list), freed_t, link);
 		list_remove(&f->link);
 		free(f);
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/fs/fat/fat_ops.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -67,5 +67,5 @@
 
 /** List of cached free FAT nodes. */
-static LIST_INITIALIZE(ffn_head);
+static LIST_INITIALIZE(ffn_list);
 
 /*
@@ -147,5 +147,4 @@
 static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
 {
-	link_t *lnk;
 	fat_node_t *nodep;
 	int rc;
@@ -159,5 +158,5 @@
 restart:
 	fibril_mutex_lock(&ffn_mutex);
-	for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
+	list_foreach(ffn_list, lnk) {
 		nodep = list_get_instance(lnk, fat_node_t, ffn_link);
 		if (!fibril_mutex_trylock(&nodep->lock)) {
@@ -196,5 +195,5 @@
 		free(nodep);
 
-		/* Need to restart because we changed the ffn_head list. */
+		/* Need to restart because we changed ffn_list. */
 		goto restart;
 	}
@@ -211,8 +210,9 @@
 
 	fibril_mutex_lock(&ffn_mutex);
-	if (!list_empty(&ffn_head)) {
+	if (!list_empty(&ffn_list)) {
 		/* Try to use a cached free node structure. */
 		fat_idx_t *idxp_tmp;
-		nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
+		nodep = list_get_instance(list_first(&ffn_list), fat_node_t,
+		    ffn_link);
 		if (!fibril_mutex_trylock(&nodep->lock))
 			goto skip_cache;
@@ -473,5 +473,5 @@
 		if (nodep->idx) {
 			fibril_mutex_lock(&ffn_mutex);
-			list_append(&nodep->ffn_link, &ffn_head);
+			list_append(&nodep->ffn_link, &ffn_list);
 			fibril_mutex_unlock(&ffn_mutex);
 		} else {
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -67,5 +67,5 @@
 	size_t size;		/**< File size if type is TMPFS_FILE. */
 	void *data;		/**< File content's if type is TMPFS_FILE. */
-	link_t cs_head;		/**< Head of child's siblings list. */
+	list_t cs_list;		/**< Child's siblings list. */
 } tmpfs_node_t;
 
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -85,5 +85,5 @@
 static int tmpfs_has_children(bool *has_children, fs_node_t *fn)
 {
-	*has_children = !list_empty(&TMPFS_NODE(fn)->cs_head);
+	*has_children = !list_empty(&TMPFS_NODE(fn)->cs_list);
 	return EOK;
 }
@@ -180,7 +180,7 @@
 	    nh_link);
 
-	while (!list_empty(&nodep->cs_head)) {
-		tmpfs_dentry_t *dentryp = list_get_instance(nodep->cs_head.next,
-		    tmpfs_dentry_t, link);
+	while (!list_empty(&nodep->cs_list)) {
+		tmpfs_dentry_t *dentryp = list_get_instance(
+		    list_first(&nodep->cs_list), tmpfs_dentry_t, link);
 
 		assert(nodep->type == TMPFS_DIRECTORY);
@@ -214,5 +214,5 @@
 	nodep->data = NULL;
 	link_initialize(&nodep->nh_link);
-	list_initialize(&nodep->cs_head);
+	list_initialize(&nodep->cs_list);
 }
 
@@ -262,8 +262,6 @@
 {
 	tmpfs_node_t *parentp = TMPFS_NODE(pfn);
-	link_t *lnk;
-
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+
+	list_foreach(parentp->cs_list, lnk) {
 		tmpfs_dentry_t *dentryp;
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
@@ -353,5 +351,5 @@
 	
 	assert(!nodep->lnkcnt);
-	assert(list_empty(&nodep->cs_head));
+	assert(list_empty(&nodep->cs_list));
 
 	unsigned long key[] = {
@@ -373,11 +371,9 @@
 	tmpfs_node_t *childp = TMPFS_NODE(cfn);
 	tmpfs_dentry_t *dentryp;
-	link_t *lnk;
 
 	assert(parentp->type == TMPFS_DIRECTORY);
 
 	/* Check for duplicit entries. */
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+	list_foreach(parentp->cs_list, lnk) {
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);	
 		if (!str_cmp(dentryp->name, nm))
@@ -401,5 +397,5 @@
 	dentryp->node = childp;
 	childp->lnkcnt++;
-	list_append(&dentryp->link, &parentp->cs_head);
+	list_append(&dentryp->link, &parentp->cs_list);
 
 	return EOK;
@@ -411,11 +407,9 @@
 	tmpfs_node_t *childp = NULL;
 	tmpfs_dentry_t *dentryp;
-	link_t *lnk;
 
 	if (!parentp)
 		return EBUSY;
 	
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+	list_foreach(parentp->cs_list, lnk) {
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
 		if (!str_cmp(dentryp->name, nm)) {
@@ -423,5 +417,5 @@
 			assert(FS_NODE(childp) == cfn);
 			break;
-		}	
+		}
 	}
 
@@ -429,5 +423,5 @@
 		return ENOENT;
 		
-	if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_head))
+	if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_list))
 		return ENOTEMPTY;
 
@@ -550,5 +544,4 @@
 		tmpfs_dentry_t *dentryp;
 		link_t *lnk;
-		aoff64_t i;
 		
 		assert(nodep->type == TMPFS_DIRECTORY);
@@ -559,10 +552,7 @@
 		 * hash table.
 		 */
-		for (i = 0, lnk = nodep->cs_head.next;
-		    (i < pos) && (lnk != &nodep->cs_head);
-		    i++, lnk = lnk->next)
-			;
-
-		if (lnk == &nodep->cs_head) {
+		lnk = list_nth(&nodep->cs_list, pos);
+		
+		if (lnk == NULL) {
 			async_answer_0(callid, ENOENT);
 			async_answer_1(rid, ENOENT, 0);
Index: pace/srv/hid/adb_mouse/Makefile
===================================================================
--- uspace/srv/hid/adb_mouse/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Jiri Svoboda
-# 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.
-#
-
-USPACE_PREFIX = ../../..
-EXTRA_CFLAGS = -Iinclude
-BINARY = adb_ms
-
-SOURCES = \
-	adb_mouse.c \
-	adb_dev.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hid/adb_mouse/adb_dev.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_dev.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,107 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * 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 mouse
- * @{
- */ 
-/** @file
- * @brief
- */
-
-#include <ipc/adb.h>
-#include <async.h>
-#include <vfs/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <devmap.h>
-#include <devmap_obsolete.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <kernel/ipc/ipc_methods.h>
-
-#include "adb_mouse.h"
-#include "adb_dev.h"
-
-static void adb_dev_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-
-int adb_dev_init(void)
-{
-	devmap_handle_t handle;
-	int rc = devmap_device_get_handle("adb/mouse", &handle,
-	    IPC_FLAG_BLOCKING);
-	
-	if (rc != EOK) {
-		printf("%s: Failed resolving ADB\n", NAME);
-		return rc;
-	}
-	
-	int dev_phone = devmap_obsolete_device_connect(handle, IPC_FLAG_BLOCKING);
-	if (dev_phone < 0) {
-		printf("%s: Failed connecting to ADB\n", NAME);
-		return ENOENT;
-	}
-	
-	/* NB: The callback connection is slotted for removal */
-	if (async_obsolete_connect_to_me(dev_phone, 0, 0, 0, adb_dev_events,
-	    NULL) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return false;
-	}
-	
-	return 0;
-}
-
-static void adb_dev_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			/* TODO: Handle hangup */
-			return;
-		}
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_FIRST_USER_METHOD:
-			mouse_handle_data(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/adb_mouse/adb_dev.h
===================================================================
--- uspace/srv/hid/adb_mouse/adb_dev.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * 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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef ADBDEV_H_
-#define ADBDEV_H_
-
-#include <sys/types.h>
-
-extern int adb_dev_init(void);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: pace/srv/hid/adb_mouse/adb_mouse.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_mouse.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,178 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * 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 mouse
- * @brief ADB Apple classic mouse driver.
- *
- * This driver handles a mouse connected to Apple Desktop Bus speaking
- * the Apple classic protocol. It connects to an ADB driver.
- *
- * @{
- */
-/** @file
- */
-
-#include <ipc/mouse.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <errno.h>
-#include <devmap.h>
-#include "adb_mouse.h"
-#include "adb_dev.h"
-
-// FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-static void mouse_ev_btn(int button, int press);
-static void mouse_ev_move(int dx, int dy);
-
-static int client_phone = -1;
-static bool b1_pressed, b2_pressed;
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": Chardev mouse driver\n");
-
-	/* Initialize device. */
-	if (adb_dev_init() != 0)
-		return -1;
-
-	b1_pressed = false;
-	b2_pressed = false; 
-
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
-	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
-		return -1;
-	}
-
-	char dev_path[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(dev_path, DEVMAP_NAME_MAXLEN, "%s/mouse", NAMESPACE);
-
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(dev_path, &devmap_handle) != EOK) {
-		printf(NAME ": Unable to register device %s\n", dev_path);
-		return -1;
-	}
-
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached. */
-	return 0;
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			if (client_phone != -1) {
-				async_obsolete_hangup(client_phone);
-				client_phone = -1;
-			}
-
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_CONNECT_TO_ME:
-			if (client_phone != -1) {
-				retval = ELIMIT;
-				break;
-			}
-			client_phone = IPC_GET_ARG5(call);
-			retval = 0;
-			break;
-		default:
-			retval = EINVAL;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-void mouse_handle_data(uint16_t data)
-{
-	bool b1, b2;
-	uint16_t udx, udy;
-	int dx, dy;
-
-	/* Extract fields. */
-	b1 = ((data >> 15) & 1) == 0;
-	udy = (data >> 8) & 0x7f;
-	b2 = ((data >> 7) & 1) == 0;
-	udx = data & 0x7f;
-
-	/* Decode 7-bit two's complement signed values. */
-	dx = (udx & 0x40) ? (udx - 0x80) : udx;
-	dy = (udy & 0x40) ? (udy - 0x80) : udy;
-
-	if (b1 != b1_pressed) {
-		mouse_ev_btn(1, b1);
-		b1_pressed = b1;
-	}
-
-	if (b2 != b2_pressed) {
-		mouse_ev_btn(2, b2);
-		b1_pressed = b1;
-	}
-
-	if (dx != 0 || dy != 0)
-		mouse_ev_move(dx, dy);
-}
-
-static void mouse_ev_btn(int button, int press)
-{
-	if (client_phone != -1) {
-		async_obsolete_msg_2(client_phone, MEVENT_BUTTON, button, press);
-	}
-}
-
-static void mouse_ev_move(int dx, int dy)
-{
-	if (client_phone != -1)
-		async_obsolete_msg_2(client_phone, MEVENT_MOVE, dx, dy);
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/adb_mouse/adb_mouse.h
===================================================================
--- uspace/srv/hid/adb_mouse/adb_mouse.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * 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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef ADB_MOUSE_H_
-#define ADB_MOUSE_H_
-
-#include <sys/types.h>
-
-#define NAME       "adb_ms"
-#define NAMESPACE  "hid_in"
-
-extern void mouse_handle_data(uint16_t);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/Makefile
===================================================================
--- uspace/srv/hid/char_mouse/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,39 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# 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.
-#
-
-USPACE_PREFIX = ../../..
-EXTRA_CFLAGS = -Iinclude
-BINARY = char_ms
-
-SOURCES = \
-	proto/ps2.c \
-	char_mouse.c \
-	chardev.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hid/char_mouse/char_mouse.c
===================================================================
--- uspace/srv/hid/char_mouse/char_mouse.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,157 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 mouse
- * @brief Chardev mouse driver.
- *
- * This is a common driver for mice attached to simple character devices
- * (PS/2 mice, serial mice).
- *
- * @{
- */
-/** @file
- */
-
-#include <ipc/mouse.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <errno.h>
-#include <devmap.h>
-#include <char_mouse.h>
-#include <mouse_port.h>
-#include <mouse_proto.h>
-
-// FIXME: remove this header
-#include <kernel/ipc/ipc_methods.h>
-
-#define NAME       "mouse"
-#define NAMESPACE  "hid_in"
-
-int client_phone = -1;
-
-void mouse_handle_byte(int byte)
-{
-/*	printf("mouse byte: 0x%x\n", byte);*/
-	mouse_proto_parse_byte(byte);
-}
-
-void mouse_ev_btn(int button, int press)
-{
-/*	printf("ev_btn: button %d, press %d\n", button, press);*/
-	if (client_phone != -1) {
-		async_obsolete_msg_2(client_phone, MEVENT_BUTTON, button, press);
-	}
-}
-
-void mouse_ev_move(int dx, int dy)
-{
-/*	printf("ev_move: dx %d, dy %d\n", dx, dy);*/
-	if (client_phone != -1)
-		async_obsolete_msg_2(client_phone, MEVENT_MOVE, dx, dy);
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			if (client_phone != -1) {
-				async_obsolete_hangup(client_phone);
-				client_phone = -1;
-			}
-
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_CONNECT_TO_ME:
-			if (client_phone != -1) {
-				retval = ELIMIT;
-				break;
-			}
-			client_phone = IPC_GET_ARG5(call);
-			retval = 0;
-			break;
-		default:
-			retval = EINVAL;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": Chardev mouse driver\n");
-
-	/* Initialize port. */
-	if (mouse_port_init() != 0)
-		return -1;
-
-	/* Initialize protocol driver. */
-	if (mouse_proto_init() != 0)
-		return -1;
-
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
-	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
-		return -1;
-	}
-
-	char dev_path[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(dev_path, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
-
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(dev_path, &devmap_handle) != EOK) {
-		printf(NAME ": Unable to register device %s\n", dev_path);
-		return -1;
-	}
-
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached. */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/chardev.c
===================================================================
--- uspace/srv/hid/char_mouse/chardev.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,121 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 mouse
- * @{
- */ 
-/** @file
- * @brief
- */
-
-#include <ipc/char.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <vfs/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <devmap.h>
-#include <devmap_obsolete.h>
-#include <char_mouse.h>
-#include <mouse_port.h>
-
-static void chardev_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-
-static int dev_phone;
-
-#define NAME "char_mouse"
-
-int mouse_port_init(void)
-{
-	devmap_handle_t handle;
-	int rc = devmap_device_get_handle("char/ps2b", &handle,
-	    IPC_FLAG_BLOCKING);
-	
-	if (rc != EOK) {
-		printf("%s: Failed resolving PS/2\n", NAME);
-		return rc;
-	}
-	
-	dev_phone = devmap_obsolete_device_connect(handle, IPC_FLAG_BLOCKING);
-	if (dev_phone < 0) {
-		printf("%s: Failed connecting to PS/2\n", NAME);
-		return ENOENT;
-	}
-	
-	/* NB: The callback connection is slotted for removal */
-	if (async_obsolete_connect_to_me(dev_phone, 0, 0, 0, chardev_events,
-	    NULL) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return false;
-	}
-	
-	return 0;
-}
-
-void mouse_port_yield(void)
-{
-}
-
-void mouse_port_reclaim(void)
-{
-}
-
-void mouse_port_write(uint8_t data)
-{
-	async_obsolete_msg_1(dev_phone, CHAR_WRITE_BYTE, data);
-}
-
-static void chardev_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-		
-		if (!IPC_GET_IMETHOD(call)) {
-			/* TODO: Handle hangup */
-			return;
-		}
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_FIRST_USER_METHOD:
-			mouse_handle_byte(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/include/char_mouse.h
===================================================================
--- uspace/srv/hid/char_mouse/include/char_mouse.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef CHAR_MOUSE_H_
-#define CHAR_MOUSE_H_
-
-extern void mouse_handle_byte(int);
-extern void mouse_ev_btn(int button, int press);
-extern void mouse_ev_move(int dx, int dy);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/include/mouse_port.h
===================================================================
--- uspace/srv/hid/char_mouse/include/mouse_port.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_PORT_H_
-#define MOUSE_PORT_H_
-
-#include <sys/types.h>
-
-extern int mouse_port_init(void);
-extern void mouse_port_yield(void);
-extern void mouse_port_reclaim(void);
-extern void mouse_port_write(uint8_t);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: pace/srv/hid/char_mouse/include/mouse_proto.h
===================================================================
--- uspace/srv/hid/char_mouse/include/mouse_proto.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_PROTO_H_
-#define MOUSE_PROTO_H_
-
-extern void mouse_proto_parse_byte(int);
-extern int mouse_proto_init(void);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/proto/ps2.c
===================================================================
--- uspace/srv/hid/char_mouse/proto/ps2.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * 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 mouse
- * @{
- */
-/**
- * @file
- * @brief PS/2 mouse protocol driver.
- */
-
-#include <stdio.h>
-#include <mouse_port.h>
-#include <char_mouse.h>
-#include <mouse_proto.h>
-
-#define BUFSIZE 3
-
-#define PS2_MOUSE_OUT_INIT  0xf4
-#define PS2_MOUSE_ACK       0xfa
-
-typedef struct {
-	union {
-		unsigned char data[BUFSIZE];
-		struct {
-			unsigned leftbtn : 1;
-			unsigned rightbtn : 1;
-			unsigned middlebtn : 1;
-			unsigned isone : 1; /* Always one */
-			unsigned xsign : 1;
-			unsigned ysign : 1;
-			unsigned xovfl : 1;
-			unsigned yovfl : 1;
-			unsigned char x;
-			unsigned char y;
-		} val;
-	} u;
-} ps2packet_t;
-
-static ps2packet_t buf;
-static int bufpos = 0;
-static int leftbtn = 0;
-static int rightbtn = 0;
-static int middlebtn = 0;
-
-int mouse_proto_init(void)
-{
-	mouse_port_write(PS2_MOUSE_OUT_INIT);
-	return 0;
-}
-
-/** Convert 9-bit 2-complement signed number to integer */
-static int bit9toint(int sign, unsigned char data)
-{
-	int tmp;
-
-	if (!sign)
-		return data;
-
-	tmp = ((unsigned char)~data) + 1;
-	return -tmp;
-}
-
-/** Process mouse data */
-void mouse_proto_parse_byte(int data)
-{
-	int x, y;
-
-	/* Check that we have not lost synchronization */
-	if (bufpos == 0 && !(data & 0x8))
-		return; /* Synchro lost, ignore byte */
-
-	buf.u.data[bufpos++] = data;
-	if (bufpos == BUFSIZE) {
-		bufpos = 0;
-
-		if (buf.u.val.leftbtn ^ leftbtn) {
-			leftbtn = buf.u.val.leftbtn;
-			mouse_ev_btn(1, leftbtn);
-		}
-
-		if (buf.u.val.rightbtn ^ rightbtn) {
-			rightbtn = buf.u.val.rightbtn;
-			mouse_ev_btn(2, rightbtn);
-		}
-
-		if (buf.u.val.middlebtn ^ middlebtn) {
-			middlebtn = buf.u.val.middlebtn;
-			mouse_ev_btn(3, middlebtn);
-		}
-
-		x =   bit9toint(buf.u.val.xsign, buf.u.val.x);
-		y = - bit9toint(buf.u.val.ysign, buf.u.val.y);
-
-		if (x != 0 || y != 0) {
-			mouse_ev_move(x, y);
-		}
-	}
-
-	return;
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/console/console.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -54,5 +54,4 @@
 #include <event.h>
 #include <devmap.h>
-#include <devmap_obsolete.h>
 #include <fcntl.h>
 #include <vfs/vfs.h>
@@ -68,6 +67,6 @@
 #define NAMESPACE  "term"
 
-/** Phone to the input server. */
-static int input_phone;
+/** Session with the input server. */
+static async_sess_t *input_sess;
 
 /** Information about framebuffer */
@@ -109,4 +108,16 @@
 static FIBRIL_CONDVAR_INITIALIZE(input_cv);
 
+static FIBRIL_MUTEX_INITIALIZE(big_console_lock);
+
+static void console_serialize_start(void)
+{
+	fibril_mutex_lock(&big_console_lock);
+}
+
+static void console_serialize_end(void)
+{
+	fibril_mutex_unlock(&big_console_lock);
+}
+
 static void curs_visibility(bool visible)
 {
@@ -141,10 +152,26 @@
 static void input_yield(void)
 {
-	async_obsolete_req_0_0(input_phone, INPUT_YIELD);
+	async_exch_t *exch = async_exchange_begin(input_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with input device.\n",
+		    NAME);
+		return;
+	}
+	
+	async_req_0_0(exch, INPUT_YIELD);
+	async_exchange_end(exch);
 }
 
 static void input_reclaim(void)
 {
-	async_obsolete_req_0_0(input_phone, INPUT_RECLAIM);
+	async_exch_t *exch = async_exchange_begin(input_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with input device.\n",
+		    NAME);
+		return;
+	}
+	
+	async_req_0_0(exch, INPUT_RECLAIM);
+	async_exchange_end(exch);
 }
 
@@ -323,10 +350,10 @@
 	
 	if (cons == kernel_console) {
-		async_obsolete_serialize_start();
+		console_serialize_start();
 		curs_hide_sync();
 		gcons_in_kernel();
 		screen_yield();
 		input_yield();
-		async_obsolete_serialize_end();
+		console_serialize_end();
 		
 		if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
@@ -338,5 +365,5 @@
 	
 	if (cons != kernel_console) {
-		async_obsolete_serialize_start();
+		console_serialize_start();
 		
 		if (active_console == kernel_console) {
@@ -393,5 +420,5 @@
 		curs_visibility(cons->scr.is_cursor_visible);
 		
-		async_obsolete_serialize_end();
+		console_serialize_end();
 	}
 }
@@ -410,5 +437,5 @@
 		if (!IPC_GET_IMETHOD(call)) {
 			/* TODO: Handle hangup */
-			async_obsolete_hangup(input_phone);
+			async_hangup(input_sess);
 			return;
 		}
@@ -455,4 +482,5 @@
 			retval = ENOENT;
 		}
+
 		async_answer_0(callid, retval);
 	}
@@ -470,5 +498,5 @@
 	}
 	
-	async_obsolete_serialize_start();
+	console_serialize_start();
 	
 	size_t off = 0;
@@ -478,5 +506,5 @@
 	}
 	
-	async_obsolete_serialize_end();
+	console_serialize_end();
 	
 	gcons_notify_char(cons->index);
@@ -573,5 +601,5 @@
 	int rc;
 	
-	async_obsolete_serialize_start();
+	console_serialize_start();
 	if (cons->refcount == 0)
 		gcons_notify_connect(cons->index);
@@ -583,7 +611,7 @@
 	
 	while (true) {
-		async_obsolete_serialize_end();
+		console_serialize_end();
 		callid = async_get_call(&call);
-		async_obsolete_serialize_start();
+		console_serialize_start();
 		
 		arg1 = 0;
@@ -595,4 +623,5 @@
 			if (cons->refcount == 0)
 				gcons_notify_disconnect(cons->index);
+			console_serialize_end();
 			return;
 		}
@@ -600,12 +629,12 @@
 		switch (IPC_GET_IMETHOD(call)) {
 		case VFS_OUT_READ:
-			async_obsolete_serialize_end();
+			console_serialize_end();
 			cons_read(cons, callid, &call);
-			async_obsolete_serialize_start();
+			console_serialize_start();
 			continue;
 		case VFS_OUT_WRITE:
-			async_obsolete_serialize_end();
+			console_serialize_end();
 			cons_write(cons, callid, &call);
-			async_obsolete_serialize_start();
+			console_serialize_start();
 			continue;
 		case VFS_OUT_SYNC:
@@ -678,7 +707,7 @@
 			break;
 		case CONSOLE_GET_EVENT:
-			async_obsolete_serialize_end();
+			console_serialize_end();
 			cons_get_event(cons, callid, &call);
-			async_obsolete_serialize_start();
+			console_serialize_start();
 			continue;
 		case CONSOLE_KCON_ENABLE:
@@ -695,32 +724,40 @@
 }
 
-static int connect_input(const char *dev_path)
-{
-	int phone;
+static async_sess_t *connect_input(const char *dev_path)
+{
+	async_sess_t *sess;
+	async_exch_t *exch;
 	devmap_handle_t handle;
 	
 	int rc = devmap_device_get_handle(dev_path, &handle, 0);
 	if (rc == EOK) {
-		phone = devmap_obsolete_device_connect(handle, 0);
-		if (phone < 0) {
-			printf("%s: Failed to connect to input device\n", NAME);
-			return phone;
+		sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+		if (sess == NULL) {
+			printf("%s: Failed to connect to input server\n", NAME);
+			return NULL;
 		}
 	} else {
-		return rc;
+		return NULL;
+	}
+	
+	exch = async_exchange_begin(sess);
+	if (exch == NULL) {
+		printf("%s: Failed to create callback from input server.\n", NAME);
+		return NULL;
 	}
 	
 	/* NB: The callback connection is slotted for removal */
-	rc = async_obsolete_connect_to_me(phone, SERVICE_CONSOLE, 0, 0,
-	    input_events, NULL);
+	rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
+
+	async_exchange_end(exch);
 
 	if (rc != EOK) {
-		async_obsolete_hangup(phone);
-		printf("%s: Failed to create callback from input device (%s).\n",
+		async_hangup(sess);
+		printf("%s: Failed to create callback from input server (%s).\n",
 		    NAME, str_error(rc));
-		return rc;
-	}
-	
-	return phone;
+		return NULL;
+	}
+	
+	return sess;
 }
 
@@ -728,6 +765,6 @@
 {
 	/* Connect to input server */
-	input_phone = connect_input(input_dev);
-	if (input_phone < 0)
+	input_sess = connect_input(input_dev);
+	if (input_sess == NULL)
 		return false;
 	
@@ -800,5 +837,5 @@
 	
 	/* Initialize the screen */
-	async_obsolete_serialize_start();
+	console_serialize_start();
 	gcons_redraw_console();
 	set_style(STYLE_NORMAL);
@@ -806,5 +843,5 @@
 	curs_goto(0, 0);
 	curs_visibility(active_console->scr.is_cursor_visible);
-	async_obsolete_serialize_end();
+	console_serialize_end();
 	
 	/* Receive kernel notifications */
Index: uspace/srv/hid/input/Makefile
===================================================================
--- uspace/srv/hid/input/Makefile	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/Makefile	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -36,5 +36,4 @@
 	generic/input.c \
 	generic/layout.c \
-	generic/mouse.c \
 	generic/stroke.c \
 	layout/cz.c \
@@ -42,5 +41,7 @@
 	layout/us_dvorak.c \
 	port/adb.c \
+	port/adb_mouse.c \
 	port/chardev.c \
+	port/chardev_mouse.c \
 	port/gxemul.c \
 	port/msim.c \
@@ -51,4 +52,7 @@
 	port/ski.c \
 	port/z8530.c \
+	proto/adb.c \
+	proto/mousedev.c \
+	proto/ps2.c \
 	ctl/apple.c \
 	ctl/gxe_fb.c \
Index: uspace/srv/hid/input/ctl/apple.c
===================================================================
--- uspace/srv/hid/input/ctl/apple.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/ctl/apple.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -33,5 +33,5 @@
 /**
  * @file
- * @brief	Apple ADB keyboard controller driver.
+ * @brief Apple ADB keyboard controller driver.
  */
 
@@ -42,10 +42,10 @@
 #include <kbd_port.h>
 
-static void apple_ctl_parse_scancode(int);
+static void apple_ctl_parse(sysarg_t);
 static int apple_ctl_init(kbd_dev_t *);
-static void apple_ctl_set_ind(kbd_dev_t *, unsigned);
+static void apple_ctl_set_ind(kbd_dev_t *, unsigned int);
 
 kbd_ctl_ops_t apple_ctl = {
-	.parse_scancode = apple_ctl_parse_scancode,
+	.parse = apple_ctl_parse,
 	.init = apple_ctl_init,
 	.set_ind = apple_ctl_set_ind
@@ -64,10 +64,10 @@
 }
 
-static void apple_ctl_parse_scancode(int scancode)
+static void apple_ctl_parse(sysarg_t scancode)
 {
 	kbd_event_type_t type;
 	unsigned int key;
 
-	if (scancode < 0 || scancode >= 0x100)
+	if (scancode >= 0x100)
 		return;
 
@@ -81,5 +81,5 @@
 	key = scanmap[scancode];
 	if (key != 0)
-		kbd_push_ev(kbd_dev, type, key);
+		kbd_push_event(kbd_dev, type, key);
 }
 
Index: uspace/srv/hid/input/ctl/gxe_fb.c
===================================================================
--- uspace/srv/hid/input/ctl/gxe_fb.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/ctl/gxe_fb.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -44,10 +44,10 @@
 #include <stroke.h>
 
-static void gxe_fb_ctl_parse_scancode(int);
+static void gxe_fb_ctl_parse(sysarg_t);
 static int gxe_fb_ctl_init(kbd_dev_t *);
-static void gxe_fb_ctl_set_ind(kbd_dev_t *, unsigned);
+static void gxe_fb_ctl_set_ind(kbd_dev_t *, unsigned int);
 
 kbd_ctl_ops_t gxe_fb_ctl = {
-	.parse_scancode = gxe_fb_ctl_parse_scancode,
+	.parse = gxe_fb_ctl_parse,
 	.init = gxe_fb_ctl_init,
 	.set_ind = gxe_fb_ctl_set_ind
@@ -229,5 +229,5 @@
 }
 
-static void gxe_fb_ctl_parse_scancode(int scancode)
+static void gxe_fb_ctl_parse(sysarg_t scancode)
 {
 	unsigned mods, key;
Index: uspace/srv/hid/input/ctl/kbdev.c
===================================================================
--- uspace/srv/hid/input/ctl/kbdev.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/ctl/kbdev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -53,10 +53,10 @@
 
 static int kbdev_ctl_init(kbd_dev_t *);
-static void kbdev_ctl_set_ind(kbd_dev_t *, unsigned);
+static void kbdev_ctl_set_ind(kbd_dev_t *, unsigned int);
 
 static void kbdev_callback_conn(ipc_callid_t, ipc_call_t *, void *arg);
 
 kbd_ctl_ops_t kbdev_ctl = {
-	.parse_scancode = NULL,
+	.parse = NULL,
 	.init = kbdev_ctl_init,
 	.set_ind = kbdev_ctl_set_ind
@@ -116,5 +116,5 @@
 	sess = fd_session(EXCHANGE_SERIALIZE, fd);
 	if (sess == NULL) {
-		printf(NAME ": Failed starting session with '%s'\n", pathname);
+		printf("%s: Failed starting session with '%s'\n", NAME, pathname);
 		close(fd);
 		return -1;
@@ -123,6 +123,6 @@
 	kbdev = kbdev_new(kdev);
 	if (kbdev == NULL) {
-		printf(NAME ": Failed allocating device structure for '%s'.\n",
-		    pathname);
+		printf("%s: Failed allocating device structure for '%s'.\n",
+		    NAME, pathname);
 		return -1;
 	}
@@ -133,5 +133,5 @@
 	exch = async_exchange_begin(sess);
 	if (exch == NULL) {
-		printf(NAME ": Failed starting exchange with '%s'.\n", pathname);
+		printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname);
 		kbdev_destroy(kbdev);
 		return -1;
@@ -140,6 +140,6 @@
 	rc = async_connect_to_me(exch, 0, 0, 0, kbdev_callback_conn, kbdev);
 	if (rc != EOK) {
-		printf(NAME ": Failed creating callback connection from '%s'.\n",
-		    pathname);
+		printf("%s: Failed creating callback connection from '%s'.\n",
+		    NAME, pathname);
 		async_exchange_end(exch);
 		kbdev_destroy(kbdev);
@@ -193,5 +193,5 @@
 			type = IPC_GET_ARG1(call);
 			key = IPC_GET_ARG2(call);
-			kbd_push_ev(kbdev->kbd_dev, type, key);
+			kbd_push_event(kbdev->kbd_dev, type, key);
 			break;
 		default:
Index: uspace/srv/hid/input/ctl/pc.c
===================================================================
--- uspace/srv/hid/input/ctl/pc.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/ctl/pc.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -43,10 +43,10 @@
 #include <gsp.h>
 
-static void pc_ctl_parse_scancode(int);
+static void pc_ctl_parse(sysarg_t);
 static int pc_ctl_init(kbd_dev_t *);
-static void pc_ctl_set_ind(kbd_dev_t *, unsigned);
+static void pc_ctl_set_ind(kbd_dev_t *, unsigned int);
 
 kbd_ctl_ops_t pc_ctl = {
-	.parse_scancode = pc_ctl_parse_scancode,
+	.parse = pc_ctl_parse,
 	.init = pc_ctl_init,
 	.set_ind = pc_ctl_set_ind
@@ -215,5 +215,5 @@
 }
 
-static void pc_ctl_parse_scancode(int scancode)
+static void pc_ctl_parse(sysarg_t scancode)
 {
 	kbd_event_type_t type;
@@ -257,10 +257,10 @@
 	}
 
-	if ((scancode < 0) || ((size_t) scancode >= map_length))
+	if ((size_t) scancode >= map_length)
 		return;
 
 	key = map[scancode];
 	if (key != 0)
-		kbd_push_ev(kbd_dev, type, key);
+		kbd_push_event(kbd_dev, type, key);
 }
 
Index: uspace/srv/hid/input/ctl/stty.c
===================================================================
--- uspace/srv/hid/input/ctl/stty.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/ctl/stty.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -33,5 +33,5 @@
 /**
  * @file
- * @brief	Serial TTY-like keyboard controller driver.
+ * @brief Serial TTY-like keyboard controller driver.
  */
 
@@ -43,10 +43,10 @@
 #include <stroke.h>
 
-static void stty_ctl_parse_scancode(int);
+static void stty_ctl_parse(sysarg_t);
 static int stty_ctl_init(kbd_dev_t *);
-static void stty_ctl_set_ind(kbd_dev_t *, unsigned);
+static void stty_ctl_set_ind(kbd_dev_t *, unsigned int);
 
 kbd_ctl_ops_t stty_ctl = {
-	.parse_scancode = stty_ctl_parse_scancode,
+	.parse = stty_ctl_parse,
 	.init = stty_ctl_init,
 	.set_ind = stty_ctl_set_ind
@@ -228,5 +228,5 @@
 }
 
-static void stty_ctl_parse_scancode(int scancode)
+static void stty_ctl_parse(sysarg_t scancode)
 {
 	unsigned mods, key;
Index: uspace/srv/hid/input/ctl/sun.c
===================================================================
--- uspace/srv/hid/input/ctl/sun.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/ctl/sun.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -34,5 +34,5 @@
 /**
  * @file
- * @brief	Sun keyboard controller driver.
+ * @brief Sun keyboard controller driver.
  */
 
@@ -43,10 +43,10 @@
 #include <kbd_port.h>
 
-static void sun_ctl_parse_scancode(int);
+static void sun_ctl_parse(sysarg_t);
 static int sun_ctl_init(kbd_dev_t *);
-static void sun_ctl_set_ind(kbd_dev_t *, unsigned);
+static void sun_ctl_set_ind(kbd_dev_t *, unsigned int);
 
 kbd_ctl_ops_t sun_ctl = {
-	.parse_scancode = sun_ctl_parse_scancode,
+	.parse = sun_ctl_parse,
 	.init = sun_ctl_init,
 	.set_ind = sun_ctl_set_ind
@@ -66,10 +66,10 @@
 }
 
-static void sun_ctl_parse_scancode(int scancode)
+static void sun_ctl_parse(sysarg_t scancode)
 {
 	kbd_event_type_t type;
 	unsigned int key;
 
-	if (scancode < 0 || scancode >= 0x100)
+	if (scancode >= 0x100)
 		return;
 
@@ -86,5 +86,5 @@
 	key = scanmap_simple[scancode];
 	if (key != 0)
-		kbd_push_ev(kbd_dev, type, key);
+		kbd_push_event(kbd_dev, type, key);
 }
 
Index: uspace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/generic/input.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -58,4 +58,5 @@
 #include <kbd_port.h>
 #include <kbd_ctl.h>
+#include <mouse_proto.h>
 #include <layout.h>
 #include <mouse.h>
@@ -65,23 +66,7 @@
 
 /* In microseconds */
-#define DISCOVERY_POLL_INTERVAL		(10*1000*1000)
-
-static void kbd_devs_yield(void);
-static void kbd_devs_reclaim(void);
-
-static void input_event_key(int, unsigned int, unsigned, wchar_t);
-
-int client_phone = -1;
-
-/** List of keyboard devices */
-static link_t kbd_devs;
-
-/** List of mouse devices */
-link_t mouse_devs;
-
-bool irc_service = false;
-int irc_phone = -1;
-
-#define NUM_LAYOUTS 3
+#define DISCOVERY_POLL_INTERVAL  (10 * 1000 * 1000)
+
+#define NUM_LAYOUTS  3
 
 static layout_ops_t *layout[NUM_LAYOUTS] = {
@@ -91,15 +76,33 @@
 };
 
-void kbd_push_scancode(kbd_dev_t *kdev, int scancode)
-{
-/*	printf("scancode: 0x%x\n", scancode);*/
-	(*kdev->ctl_ops->parse_scancode)(scancode);
-}
-
-void kbd_push_ev(kbd_dev_t *kdev, int type, unsigned int key)
+static void kbd_devs_yield(void);
+static void kbd_devs_reclaim(void);
+
+int client_phone = -1;
+
+/** List of keyboard devices */
+static list_t kbd_devs;
+
+/** List of mouse devices */
+static list_t mouse_devs;
+
+bool irc_service = false;
+int irc_phone = -1;
+
+void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
+{
+	(*kdev->ctl_ops->parse)(data);
+}
+
+void mouse_push_data(mouse_dev_t *mdev, sysarg_t data)
+{
+	(*mdev->proto_ops->parse)(data);
+}
+
+void kbd_push_event(kbd_dev_t *kdev, int type, unsigned int key)
 {
 	kbd_event_t ev;
-	unsigned mod_mask;
-
+	unsigned int mod_mask;
+	
 	switch (key) {
 	case KC_LCTRL: mod_mask = KM_LCTRL; break;
@@ -111,5 +114,5 @@
 	default: mod_mask = 0; break;
 	}
-
+	
 	if (mod_mask != 0) {
 		if (type == KEY_PRESS)
@@ -118,5 +121,5 @@
 			kdev->mods = kdev->mods & ~mod_mask;
 	}
-
+	
 	switch (key) {
 	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
@@ -125,5 +128,5 @@
 	default: mod_mask = 0; break;
 	}
-
+	
 	if (mod_mask != 0) {
 		if (type == KEY_PRESS) {
@@ -135,5 +138,5 @@
 			kdev->mods = kdev->mods ^ (mod_mask & ~kdev->lock_keys);
 			kdev->lock_keys = kdev->lock_keys | mod_mask;
-
+			
 			/* Update keyboard lock indicator lights. */
 			(*kdev->ctl_ops->set_ind)(kdev, kdev->mods);
@@ -142,48 +145,37 @@
 		}
 	}
-/*
-	printf("type: %d\n", type);
-	printf("mods: 0x%x\n", mods);
-	printf("keycode: %u\n", key);
-*/
+	
 	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
-		key == KC_F1) {
+	    key == KC_F1) {
 		layout_destroy(kdev->active_layout);
 		kdev->active_layout = layout_create(layout[0]);
 		return;
 	}
-
+	
 	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
-		key == KC_F2) {
+	    key == KC_F2) {
 		layout_destroy(kdev->active_layout);
 		kdev->active_layout = layout_create(layout[1]);
 		return;
 	}
-
+	
 	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
-		key == KC_F3) {
+	    key == KC_F3) {
 		layout_destroy(kdev->active_layout);
 		kdev->active_layout = layout_create(layout[2]);
 		return;
 	}
-
+	
 	ev.type = type;
 	ev.key = key;
 	ev.mods = kdev->mods;
-
+	
 	ev.c = layout_parse_ev(kdev->active_layout, &ev);
-	input_event_key(ev.type, ev.key, ev.mods, ev.c);
-}
-
-/** Key has been pressed or released. */
-static void input_event_key(int type, unsigned int key, unsigned mods,
-    wchar_t c)
-{
-	async_obsolete_msg_4(client_phone, INPUT_EVENT_KEY, type, key,
-	    mods, c);
+	async_obsolete_msg_4(client_phone, INPUT_EVENT_KEY, ev.type, ev.key,
+	    ev.mods, ev.c);
 }
 
 /** Mouse pointer has moved. */
-void input_event_move(int dx, int dy)
+void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy)
 {
 	async_obsolete_msg_2(client_phone, INPUT_EVENT_MOVE, dx, dy);
@@ -191,5 +183,5 @@
 
 /** Mouse button has been pressed. */
-void input_event_button(int bnum, int press)
+void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press)
 {
 	async_obsolete_msg_2(client_phone, INPUT_EVENT_BUTTON, bnum, press);
@@ -201,7 +193,7 @@
 	ipc_call_t call;
 	int retval;
-
+	
 	async_answer_0(iid, EOK);
-
+	
 	while (true) {
 		callid = async_get_call(&call);
@@ -237,26 +229,39 @@
 			retval = EINVAL;
 		}
+		
 		async_answer_0(callid, retval);
-	}	
+	}
 }
 
 static kbd_dev_t *kbd_dev_new(void)
 {
-	kbd_dev_t *kdev;
-
-	kdev = calloc(1, sizeof(kbd_dev_t));
+	kbd_dev_t *kdev = calloc(1, sizeof(kbd_dev_t));
 	if (kdev == NULL) {
-		printf(NAME ": Error allocating keyboard device. "
-		    "Out of memory.\n");
+		printf("%s: Error allocating keyboard device. "
+		    "Out of memory.\n", NAME);
 		return NULL;
 	}
-
+	
 	link_initialize(&kdev->kbd_devs);
-
+	
 	kdev->mods = KM_NUM_LOCK;
 	kdev->lock_keys = 0;
 	kdev->active_layout = layout_create(layout[0]);
-
+	
 	return kdev;
+}
+
+static mouse_dev_t *mouse_dev_new(void)
+{
+	mouse_dev_t *mdev = calloc(1, sizeof(mouse_dev_t));
+	if (mdev == NULL) {
+		printf("%s: Error allocating keyboard device. "
+		    "Out of memory.\n", NAME);
+		return NULL;
+	}
+	
+	link_initialize(&mdev->mouse_devs);
+	
+	return mdev;
 }
 
@@ -264,18 +269,16 @@
 static void kbd_add_dev(kbd_port_ops_t *port, kbd_ctl_ops_t *ctl)
 {
-	kbd_dev_t *kdev;
-
-	kdev = kbd_dev_new();
+	kbd_dev_t *kdev = kbd_dev_new();
 	if (kdev == NULL)
 		return;
-
+	
 	kdev->port_ops = port;
 	kdev->ctl_ops = ctl;
 	kdev->dev_path = NULL;
-
+	
 	/* Initialize port driver. */
 	if ((*kdev->port_ops->init)(kdev) != 0)
 		goto fail;
-
+	
 	/* Initialize controller driver. */
 	if ((*kdev->ctl_ops->init)(kdev) != 0) {
@@ -283,36 +286,93 @@
 		goto fail;
 	}
-
+	
 	list_append(&kdev->kbd_devs, &kbd_devs);
 	return;
+	
 fail:
 	free(kdev);
 }
 
+/** Add new legacy mouse device. */
+static void mouse_add_dev(mouse_port_ops_t *port, mouse_proto_ops_t *proto)
+{
+	mouse_dev_t *mdev = mouse_dev_new();
+	if (mdev == NULL)
+		return;
+	
+	mdev->port_ops = port;
+	mdev->proto_ops = proto;
+	mdev->dev_path = NULL;
+	
+	/* Initialize port driver. */
+	if ((*mdev->port_ops->init)(mdev) != 0)
+		goto fail;
+	
+	/* Initialize protocol driver. */
+	if ((*mdev->proto_ops->init)(mdev) != 0) {
+		/* XXX Uninit port */
+		goto fail;
+	}
+	
+	list_append(&mdev->mouse_devs, &mouse_devs);
+	return;
+	
+fail:
+	free(mdev);
+}
+
 /** Add new kbdev device.
  *
- * @param dev_path	Filesystem path to the device (/dev/class/...)
+ * @param dev_path Filesystem path to the device (/dev/class/...)
+ *
  */
 static int kbd_add_kbdev(const char *dev_path)
 {
-	kbd_dev_t *kdev;
-
-	kdev = kbd_dev_new();
+	kbd_dev_t *kdev = kbd_dev_new();
 	if (kdev == NULL)
 		return -1;
-
+	
 	kdev->dev_path = dev_path;
 	kdev->port_ops = NULL;
 	kdev->ctl_ops = &kbdev_ctl;
-
+	
 	/* Initialize controller driver. */
 	if ((*kdev->ctl_ops->init)(kdev) != 0) {
 		goto fail;
 	}
-
+	
 	list_append(&kdev->kbd_devs, &kbd_devs);
 	return EOK;
+	
 fail:
 	free(kdev);
+	return -1;
+}
+
+/** Add new mousedev device.
+ *
+ * @param dev_path Filesystem path to the device (/dev/class/...)
+ *
+ */
+static int mouse_add_mousedev(const char *dev_path)
+{
+	mouse_dev_t *mdev = mouse_dev_new();
+	if (mdev == NULL)
+		return -1;
+	
+	mdev->dev_path = dev_path;
+	mdev->port_ops = NULL;
+	mdev->proto_ops = &mousedev_proto;
+	
+	/* Initialize controller driver. */
+	if ((*mdev->proto_ops->init)(mdev) != 0) {
+		goto fail;
+	}
+	
+	list_append(&mdev->mouse_devs, &mouse_devs);
+	return EOK;
+	
+fail:
+	free(mdev);
 	return -1;
 }
@@ -375,4 +435,27 @@
 }
 
+/** Add legacy drivers/devices. */
+static void mouse_add_legacy_devs(void)
+{
+	/*
+	 * Need to add these drivers based on config unless we can probe
+	 * them automatically.
+	 */
+#if defined(UARCH_amd64)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(UARCH_ia32)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(MACHINE_i460GX)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(UARCH_ppc32)
+	mouse_add_dev(&adb_mouse_port, &adb_proto);
+#endif
+	/* Silence warning on abs32le about mouse_add_dev() being unused */
+	(void) mouse_add_dev;
+}
+
 static void kbd_devs_yield(void)
 {
@@ -381,5 +464,5 @@
 		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
 		    kbd_devs);
-
+		
 		/* Yield port */
 		if (kdev->port_ops != NULL)
@@ -394,5 +477,5 @@
 		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
 		    kbd_devs);
-
+		
 		/* Reclaim port */
 		if (kdev->port_ops != NULL)
@@ -405,5 +488,6 @@
  * Looks under /dev/class/keyboard and /dev/class/mouse.
  *
- * @param arg	Ignored
+ * @param arg Ignored
+ *
  */
 static int dev_discovery_fibril(void *arg)
@@ -413,8 +497,8 @@
 	size_t mouse_id = 1;
 	int rc;
-
+	
 	while (true) {
 		async_usleep(DISCOVERY_POLL_INTERVAL);
-
+		
 		/*
 		 * Check for new keyboard device
@@ -423,15 +507,15 @@
 		if (rc < 0)
 			continue;
-
+		
 		if (kbd_add_kbdev(dev_path) == EOK) {
-			printf(NAME ": Connected keyboard device '%s'\n",
-			    dev_path);
-
+			printf("%s: Connected keyboard device '%s'\n",
+			    NAME, dev_path);
+			
 			/* XXX Handle device removal */
 			++kbd_id;
 		}
-
+		
 		free(dev_path);
-
+		
 		/*
 		 * Check for new mouse device
@@ -440,16 +524,16 @@
 		if (rc < 0)
 			continue;
-
-		if (mouse_add_dev(dev_path) == EOK) {
-			printf(NAME ": Connected mouse device '%s'\n",
-			    dev_path);
-
+		
+		if (mouse_add_mousedev(dev_path) == EOK) {
+			printf("%s: Connected mouse device '%s'\n",
+			    NAME, dev_path);
+			
 			/* XXX Handle device removal */
 			++mouse_id;
 		}
-
+		
 		free(dev_path);
 	}
-
+	
 	return EOK;
 }
@@ -458,12 +542,11 @@
 static void input_start_dev_discovery(void)
 {
-	fid_t fid;
-
-	fid = fibril_create(dev_discovery_fibril, NULL);
+	fid_t fid = fibril_create(dev_discovery_fibril, NULL);
 	if (!fid) {
-		printf(NAME ": Failed to create device discovery fibril.\n");
+		printf("%s: Failed to create device discovery fibril.\n",
+		    NAME);
 		return;
 	}
-
+	
 	fibril_add_ready(fid);
 }
@@ -490,7 +573,7 @@
 	/* Add legacy keyboard devices. */
 	kbd_add_legacy_devs();
-
-	/* Add legacy (devmap-style) mouse device. */
-	(void) mouse_add_dev("/dev/hid_in/mouse");
+	
+	/* Add legacy mouse devices. */
+	mouse_add_legacy_devs();
 	
 	/* Register driver */
@@ -509,11 +592,11 @@
 		return -1;
 	}
-
+	
 	/* Start looking for new input devices */
 	input_start_dev_discovery();
-
-	printf(NAME ": Accepting connections\n");
+	
+	printf("%s: Accepting connections\n", NAME);
 	async_manager();
-
+	
 	/* Not reached. */
 	return 0;
Index: uspace/srv/hid/input/generic/layout.c
===================================================================
--- uspace/srv/hid/input/generic/layout.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/generic/layout.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -48,5 +48,5 @@
 	layout = calloc(1, sizeof(layout_t));
 	if (layout == NULL) {
-		printf(NAME ": Out of memory.\n");
+		printf("%s: Out of memory.\n", NAME);
 		return NULL;
 	}
Index: pace/srv/hid/input/generic/mouse.c
===================================================================
--- uspace/srv/hid/input/generic/mouse.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ 	(revision )
@@ -1,165 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * 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 inputgen generic
- * @brief Mouse device handling.
- * @ingroup input
- * @{
- */
-/** @file
- */
-
-#include <adt/list.h>
-#include <async.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <input.h>
-#include <ipc/mouse.h>
-#include <mouse.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <vfs/vfs_sess.h>
-
-static void mouse_callback_conn(ipc_callid_t, ipc_call_t *, void *);
-
-static mouse_dev_t *mouse_dev_new(void)
-{
-	mouse_dev_t *mdev;
-
-	mdev = calloc(1, sizeof(mouse_dev_t));
-	if (mdev == NULL) {
-		printf(NAME ": Error allocating mouse device. "
-		    "Out of memory.\n");
-		return NULL;
-	}
-
-	link_initialize(&mdev->mouse_devs);
-	return mdev;
-}
-
-static int mouse_dev_connect(mouse_dev_t *mdev, const char *dev_path)
-{
-	async_sess_t *sess;
-	async_exch_t *exch;
-	int fd;
-	int rc;
-
-	fd = open(dev_path, O_RDWR);
-	if (fd < 0) {
-		return -1;
-	}
-
-	sess = fd_session(EXCHANGE_SERIALIZE, fd);
-	if (sess == NULL) {
-		printf(NAME ": Failed starting session with '%s'\n", dev_path);
-		close(fd);
-		return -1;
-	}
-
-	exch = async_exchange_begin(sess);
-	if (exch == NULL) {
-		printf(NAME ": Failed starting exchange with '%s'.\n", dev_path);
-		return -1;
-	}
-
-	rc = async_connect_to_me(exch, 0, 0, 0, mouse_callback_conn, mdev);
-	if (rc != EOK) {
-		printf(NAME ": Failed creating callback connection from '%s'.\n",
-		    dev_path);
-		async_exchange_end(exch);
-		return -1;
-	}
-
-	async_exchange_end(exch);
-
-	mdev->dev_path = dev_path;
-	return 0;
-}
-
-/** Add new mouse device.
- *
- * @param dev_path	Filesystem path to the device (/dev/class/...)
- */
-int mouse_add_dev(const char *dev_path)
-{
-	mouse_dev_t *mdev;
-	int rc;
-
-	mdev = mouse_dev_new();
-	if (mdev == NULL)
-		return -1;
-
-	rc = mouse_dev_connect(mdev, dev_path);
-	if (rc != EOK) {
-		free(mdev);
-		return -1;
-	}
-
-	list_append(&mdev->mouse_devs, &mouse_devs);
-	return EOK;
-}
-
-/** Mouse device callback connection handler. */
-static void mouse_callback_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	int retval;
-
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid;
-
-		callid = async_get_call(&call);
-		if (!IPC_GET_IMETHOD(call)) {
-			/* XXX Handle hangup */
-			return;
-		}
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case MEVENT_BUTTON:
-			input_event_button(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			retval = 0;
-			break;
-		case MEVENT_MOVE:
-			input_event_move(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			retval = 0;
-			break;
-		default:
-			retval = ENOTSUP;
-			break;
-		}
-
-		async_answer_0(callid, retval);
-	}
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/input/generic/stroke.c
===================================================================
--- uspace/srv/hid/input/generic/stroke.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/generic/stroke.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -60,5 +60,5 @@
 	while (mods_keys[i][0] != 0) {
 		if (mod & mods_keys[i][0]) {
-			kbd_push_ev(kdev, KEY_PRESS, mods_keys[i][1]);
+			kbd_push_event(kdev, KEY_PRESS, mods_keys[i][1]);
 		}
 		++i;
@@ -67,6 +67,6 @@
 	/* Simulate key press and release. */
 	if (key != 0) {
-		kbd_push_ev(kdev, KEY_PRESS, key);
-		kbd_push_ev(kdev, KEY_RELEASE, key);
+		kbd_push_event(kdev, KEY_PRESS, key);
+		kbd_push_event(kdev, KEY_RELEASE, key);
 	}
 
@@ -75,5 +75,5 @@
 	while (mods_keys[i][0] != 0) {
 		if (mod & mods_keys[i][0]) {
-			kbd_push_ev(kdev, KEY_RELEASE, mods_keys[i][1]);
+			kbd_push_event(kdev, KEY_RELEASE, mods_keys[i][1]);
 		}
 		++i;
Index: uspace/srv/hid/input/include/input.h
===================================================================
--- uspace/srv/hid/input/include/input.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/include/input.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -42,13 +42,8 @@
 
 #define NAME       "input"
-#define NAMESPACE  "hid_in"
+#define NAMESPACE  "hid"
 
 extern bool irc_service;
 extern int irc_phone;
-
-extern link_t mouse_devs;
-
-void input_event_move(int, int);
-void input_event_button(int bnum, int press);
 
 #endif
Index: uspace/srv/hid/input/include/kbd.h
===================================================================
--- uspace/srv/hid/input/include/kbd.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/include/kbd.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -71,6 +71,6 @@
 } kbd_dev_t;
 
-extern void kbd_push_scancode(kbd_dev_t *, int);
-extern void kbd_push_ev(kbd_dev_t *, int, unsigned int);
+extern void kbd_push_data(kbd_dev_t *, sysarg_t);
+extern void kbd_push_event(kbd_dev_t *, int, unsigned int);
 
 #endif
Index: uspace/srv/hid/input/include/kbd_ctl.h
===================================================================
--- uspace/srv/hid/input/include/kbd_ctl.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/include/kbd_ctl.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -28,6 +28,6 @@
 
 /** @addtogroup inputgen generic
- * @brief	Keyboard controller driver interface.
- * @ingroup  input
+ * @brief Keyboard controller driver interface.
+ * @ingroup input
  * @{
  */
@@ -43,7 +43,7 @@
 
 typedef struct kbd_ctl_ops {
-	void (*parse_scancode)(int);
+	void (*parse)(sysarg_t);
 	int (*init)(struct kbd_dev *);
-	void (*set_ind)(struct kbd_dev *, unsigned);
+	void (*set_ind)(struct kbd_dev *, unsigned int);
 } kbd_ctl_ops_t;
 
@@ -59,4 +59,3 @@
 /**
  * @}
- */ 
-
+ */
Index: uspace/srv/hid/input/include/kbd_port.h
===================================================================
--- uspace/srv/hid/input/include/kbd_port.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/include/kbd_port.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -28,6 +28,6 @@
 
 /** @addtogroup inputgen generic
- * @brief	Keyboard port driver interface.
- * @ingroup  input
+ * @brief Keyboard port driver interface.
+ * @ingroup input
  * @{
  */
@@ -51,5 +51,4 @@
 extern kbd_port_ops_t adb_port;
 extern kbd_port_ops_t chardev_port;
-extern kbd_port_ops_t dummy_port;
 extern kbd_port_ops_t gxemul_port;
 extern kbd_port_ops_t msim_port;
@@ -65,4 +64,3 @@
 /**
  * @}
- */ 
-
+ */
Index: uspace/srv/hid/input/include/mouse.h
===================================================================
--- uspace/srv/hid/input/include/mouse.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/include/mouse.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -40,13 +40,24 @@
 #include <adt/list.h>
 
+struct mouse_port_ops;
+struct mouse_proto_ops;
+
 typedef struct mouse_dev {
 	/** Link to mouse_devs list */
 	link_t mouse_devs;
-
-	/** Path to the device */
+	
+	/** Path to the device (only for mouseev devices) */
 	const char *dev_path;
+	
+	/** Port ops */
+	struct mouse_port_ops *port_ops;
+	
+	/** Protocol ops */
+	struct mouse_proto_ops *proto_ops;
 } mouse_dev_t;
 
-int mouse_add_dev(const char *dev_path);
+extern void mouse_push_data(mouse_dev_t *, sysarg_t);
+extern void mouse_push_event_move(mouse_dev_t *, int, int);
+extern void mouse_push_event_button(mouse_dev_t *, int, int);
 
 #endif
Index: uspace/srv/hid/input/include/mouse_port.h
===================================================================
--- uspace/srv/hid/input/include/mouse_port.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/srv/hid/input/include/mouse_port.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Mouse port driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_PORT_H_
+#define MOUSE_PORT_H_
+
+#include <sys/types.h>
+
+struct mouse_dev;
+
+typedef struct mouse_port_ops {
+	int (*init)(struct mouse_dev *);
+	void (*yield)(void);
+	void (*reclaim)(void);
+	void (*write)(uint8_t);
+} mouse_port_ops_t;
+
+extern mouse_port_ops_t adb_mouse_port;
+extern mouse_port_ops_t chardev_mouse_port;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/mouse_proto.h
===================================================================
--- uspace/srv/hid/input/include/mouse_proto.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/srv/hid/input/include/mouse_proto.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Mouse protocol driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_PROTO_H_
+#define MOUSE_PROTO_H_
+
+#include <mouse_port.h>
+
+struct mouse_dev;
+
+typedef struct mouse_proto_ops {
+	void (*parse)(sysarg_t);
+	int (*init)(struct mouse_dev *);
+} mouse_proto_ops_t;
+
+extern mouse_proto_ops_t adb_proto;
+extern mouse_proto_ops_t ps2_proto;
+extern mouse_proto_ops_t mousedev_proto;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout/cz.c
===================================================================
--- uspace/srv/hid/input/layout/cz.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/layout/cz.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -391,5 +391,5 @@
 	cz_state = malloc(sizeof(layout_cz_t));
 	if (cz_state == NULL) {
-		printf(NAME ": Out of memory.\n");
+		printf("%s: Out of memory.\n", NAME);
 		return ENOMEM;
 	}
Index: uspace/srv/hid/input/port/adb.c
===================================================================
--- uspace/srv/hid/input/port/adb.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/adb.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -37,5 +37,4 @@
 #include <ipc/adb.h>
 #include <async.h>
-#include <async_obsolete.h>
 #include <input.h>
 #include <kbd_port.h>
@@ -45,5 +44,4 @@
 #include <errno.h>
 #include <devmap.h>
-#include <devmap_obsolete.h>
 
 static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
@@ -63,5 +61,5 @@
 
 static kbd_dev_t *kbd_dev;
-static int dev_phone;
+static async_sess_t *dev_sess;
 
 static int adb_port_init(kbd_dev_t *kdev)
@@ -69,22 +67,32 @@
 	const char *dev = "adb/kbd";
 	devmap_handle_t handle;
-
+	async_exch_t *exch;
+	int rc;
+	
 	kbd_dev = kdev;
 	
-	int rc = devmap_device_get_handle(dev, &handle, 0);
-	if (rc == EOK) {
-		dev_phone = devmap_obsolete_device_connect(handle, 0);
-		if (dev_phone < 0) {
-			printf("%s: Failed to connect to device\n", NAME);
-			return dev_phone;
-		}
-	} else
+	rc = devmap_device_get_handle(dev, &handle, 0);
+	if (rc != EOK)
 		return rc;
 	
+	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+	if (dev_sess == NULL) {
+		printf("%s: Failed to connect to device\n", NAME);
+		return ENOENT;
+	}
+	
+	exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
 	/* NB: The callback connection is slotted for removal */
-	rc = async_obsolete_connect_to_me(dev_phone, 0, 0, 0, kbd_port_events,
-	    NULL);
+	rc = async_connect_to_me(exch, 0, 0, 0, kbd_port_events, NULL);
+	async_exchange_end(exch);
 	if (rc != EOK) {
-		printf(NAME ": Failed to create callback from device\n");
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
 		return rc;
 	}
@@ -134,13 +142,12 @@
 static void adb_kbd_reg0_data(uint16_t data)
 {
-	uint8_t b0, b1;
-
-	b0 = (data >> 8) & 0xff;
-	b1 = data & 0xff;
-
+	uint8_t b0 = (data >> 8) & 0xff;
+	uint8_t b1 = data & 0xff;
+	
 	if (b0 != 0xff)
-		kbd_push_scancode(kbd_dev, b0);
+		kbd_push_data(kbd_dev, b0);
+	
 	if (b1 != 0xff)
-		kbd_push_scancode(kbd_dev, b1);
+		kbd_push_data(kbd_dev, b1);
 }
 
Index: uspace/srv/hid/input/port/adb_mouse.c
===================================================================
--- uspace/srv/hid/input/port/adb_mouse.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/srv/hid/input/port/adb_mouse.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_port
+ * @ingroup mouse
+ * @{
+ */
+/** @file
+ * @brief ADB mouse port driver.
+ */
+
+#include <ipc/adb.h>
+#include <async.h>
+#include <input.h>
+#include <mouse_port.h>
+#include <mouse.h>
+#include <errno.h>
+#include <devmap.h>
+
+static mouse_dev_t *mouse_dev;
+static async_sess_t *dev_sess;
+
+static void mouse_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		int retval;
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case ADB_REG_NOTIF:
+			mouse_push_data(mouse_dev, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int adb_port_init(mouse_dev_t *mdev)
+{
+	const char *dev = "adb/mouse";
+	
+	mouse_dev = mdev;
+	
+	devmap_handle_t handle;
+	int rc = devmap_device_get_handle(dev, &handle, 0);
+	if (rc != EOK)
+		return rc;
+	
+	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+	if (dev_sess == NULL) {
+		printf("%s: Failed to connect to device\n", NAME);
+		return ENOENT;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, mouse_port_events, NULL);
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+static void adb_port_yield(void)
+{
+}
+
+static void adb_port_reclaim(void)
+{
+}
+
+static void adb_port_write(uint8_t data)
+{
+}
+
+mouse_port_ops_t adb_mouse_port = {
+	.init = adb_port_init,
+	.yield = adb_port_yield,
+	.reclaim = adb_port_reclaim,
+	.write = adb_port_write
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/chardev.c
===================================================================
--- uspace/srv/hid/input/port/chardev.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/chardev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -37,10 +37,8 @@
 #include <ipc/char.h>
 #include <async.h>
-#include <async_obsolete.h>
 #include <input.h>
 #include <kbd_port.h>
 #include <kbd.h>
 #include <devmap.h>
-#include <devmap_obsolete.h>
 #include <errno.h>
 #include <stdio.h>
@@ -61,5 +59,5 @@
 
 static kbd_dev_t *kbd_dev;
-static int dev_phone;
+static async_sess_t *dev_sess;
 
 /** List of devices to try connecting to. */
@@ -74,4 +72,5 @@
 {
 	devmap_handle_t handle;
+	async_exch_t *exch;
 	unsigned int i;
 	int rc;
@@ -90,17 +89,28 @@
 	}
 	
-	dev_phone = devmap_obsolete_device_connect(handle, IPC_FLAG_BLOCKING);
-	if (dev_phone < 0) {
+	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle,
+	    IPC_FLAG_BLOCKING);
+	if (dev_sess == NULL) {
 		printf("%s: Failed connecting to device\n", NAME);
 		return ENOENT;
 	}
 	
+	exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
 	/* NB: The callback connection is slotted for removal */
-	if (async_obsolete_connect_to_me(dev_phone, 0, 0, 0, kbd_port_events,
-	    NULL) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
+	rc = async_connect_to_me(exch, 0, 0, 0, kbd_port_events, NULL);
+	async_exchange_end(exch);
+	
+	if (rc != 0) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
 		return -1;
 	}
-
+	
 	return 0;
 }
@@ -116,5 +126,12 @@
 static void chardev_port_write(uint8_t data)
 {
-	async_obsolete_msg_1(dev_phone, CHAR_WRITE_BYTE, data);
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		return;
+	}
+
+	async_msg_1(exch, CHAR_WRITE_BYTE, data);
+	async_exchange_end(exch);
 }
 
@@ -136,5 +153,5 @@
 		switch (IPC_GET_IMETHOD(call)) {
 		case CHAR_NOTIF_BYTE:
-			kbd_push_scancode(kbd_dev, IPC_GET_ARG1(call));
+			kbd_push_data(kbd_dev, IPC_GET_ARG1(call));
 			break;
 		default:
Index: uspace/srv/hid/input/port/chardev_mouse.c
===================================================================
--- uspace/srv/hid/input/port/chardev_mouse.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/srv/hid/input/port/chardev_mouse.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_port
+ * @ingroup mouse
+ * @{
+ */
+/** @file
+ * @brief Chardev mouse port driver.
+ */
+
+#include <ipc/char.h>
+#include <stdio.h>
+#include <async.h>
+#include <errno.h>
+#include <devmap.h>
+#include <input.h>
+#include <mouse_port.h>
+#include <mouse.h>
+
+static mouse_dev_t *mouse_dev;
+static async_sess_t *dev_sess;
+
+/** List of devices to try connecting to. */
+static const char *in_devs[] = {
+	"char/ps2b",
+};
+
+static const unsigned int num_devs = sizeof(in_devs) / sizeof(in_devs[0]);
+
+static void mouse_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		int retval;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case CHAR_NOTIF_BYTE:
+			mouse_push_data(mouse_dev, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int chardev_port_init(mouse_dev_t *mdev)
+{
+	devmap_handle_t handle;
+	unsigned int i;
+	int rc;
+	
+	mouse_dev = mdev;
+	
+	for (i = 0; i < num_devs; i++) {
+		rc = devmap_device_get_handle(in_devs[i], &handle, 0);
+		if (rc == EOK)
+			break;
+	}
+	
+	if (i >= num_devs) {
+		printf("%s: Could not find any suitable input device\n", NAME);
+		return -1;
+	}
+	
+	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle,
+	    IPC_FLAG_BLOCKING);
+	if (dev_sess == NULL) {
+		printf("%s: Failed connecting to device\n", NAME);
+		return ENOENT;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, mouse_port_events, NULL);
+	async_exchange_end(exch);
+	
+	if (rc != 0) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return -1;
+	}
+	
+	return 0;
+}
+
+static void chardev_port_yield(void)
+{
+}
+
+static void chardev_port_reclaim(void)
+{
+}
+
+static void chardev_port_write(uint8_t data)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		return;
+	}
+
+	async_msg_1(exch, CHAR_WRITE_BYTE, data);
+	async_exchange_end(exch);
+}
+
+mouse_port_ops_t chardev_mouse_port = {
+	.init = chardev_port_init,
+	.yield = chardev_port_yield,
+	.reclaim = chardev_port_reclaim,
+	.write = chardev_port_write
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/gxemul.c
===================================================================
--- uspace/srv/hid/input/port/gxemul.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/gxemul.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -108,15 +108,12 @@
 
 /** Process data sent when a key is pressed.
- *  
- *  @param keybuffer Buffer of pressed keys.
- *  @param call      IPC call.
  *
- *  @return Always 1.
+ * @param keybuffer Buffer of pressed keys.
+ * @param call      IPC call.
+ *
  */
 static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call)
 {
-	int scan_code = IPC_GET_ARG2(*call);
-
-	kbd_push_scancode(kbd_dev, scan_code);
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
 }
 
Index: uspace/srv/hid/input/port/msim.c
===================================================================
--- uspace/srv/hid/input/port/msim.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/msim.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -109,8 +109,7 @@
 static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call)
 {
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(kbd_dev, scan_code);
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
 }
 
 /** @}
-*/
+ */
Index: uspace/srv/hid/input/port/niagara.c
===================================================================
--- uspace/srv/hid/input/port/niagara.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/niagara.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -148,6 +148,6 @@
 		c = input_buffer->data[input_buffer->read_ptr];
 		input_buffer->read_ptr =
-			((input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
-		kbd_push_scancode(kbd_dev, c);
+		    ((input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
+		kbd_push_data(kbd_dev, c);
 	}
 }
Index: uspace/srv/hid/input/port/ns16550.c
===================================================================
--- uspace/srv/hid/input/port/ns16550.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/ns16550.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -156,6 +156,5 @@
 static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call)
 {
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(kbd_dev, scan_code);
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
 	
 	if (irc_service)
Index: uspace/srv/hid/input/port/pl050.c
===================================================================
--- uspace/srv/hid/input/port/pl050.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/pl050.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -137,11 +137,8 @@
 static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call)
 {
-	int scan_code = IPC_GET_ARG2(*call);
-
-	kbd_push_scancode(kbd_dev, scan_code);
-	return;
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
 }
 
 /**
  * @}
- */ 
+ */
Index: uspace/srv/hid/input/port/sgcn.c
===================================================================
--- uspace/srv/hid/input/port/sgcn.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/sgcn.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -183,6 +183,6 @@
 		*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
 		buf_ptr = (volatile char *)
-			SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-		kbd_push_scancode(kbd_dev, c);
+		    SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
+		kbd_push_data(kbd_dev, c);
 	}
 }
Index: uspace/srv/hid/input/port/ski.c
===================================================================
--- uspace/srv/hid/input/port/ski.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/ski.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -110,5 +110,5 @@
 			if (c == 0)
 				break;
-			kbd_push_scancode(kbd_dev, c);
+			kbd_push_data(kbd_dev, c);
 		}
 
Index: uspace/srv/hid/input/port/z8530.c
===================================================================
--- uspace/srv/hid/input/port/z8530.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/input/port/z8530.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -142,6 +142,5 @@
 static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
 {
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(kbd_dev, scan_code);
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
 	
 	if (irc_service)
Index: uspace/srv/hid/input/proto/adb.c
===================================================================
--- uspace/srv/hid/input/proto/adb.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/srv/hid/input/proto/adb.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief ADB protocol driver.
+ */
+
+#include <bool.h>
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+
+static mouse_dev_t *mouse_dev;
+static bool b1_pressed;
+static bool b2_pressed;
+
+static int adb_proto_init(mouse_dev_t *mdev)
+{
+	mouse_dev = mdev;
+	b1_pressed = false;
+	b2_pressed = false;
+	
+	return 0;
+}
+
+/** Process mouse data */
+static void adb_proto_parse(sysarg_t data)
+{
+	bool b1, b2;
+	uint16_t udx, udy;
+	int dx, dy;
+	
+	/* Extract fields. */
+	b1 = ((data >> 15) & 1) == 0;
+	udy = (data >> 8) & 0x7f;
+	b2 = ((data >> 7) & 1) == 0;
+	udx = data & 0x7f;
+	
+	/* Decode 7-bit two's complement signed values. */
+	dx = (udx & 0x40) ? (udx - 0x80) : udx;
+	dy = (udy & 0x40) ? (udy - 0x80) : udy;
+	
+	if (b1 != b1_pressed) {
+		mouse_push_event_button(mouse_dev, 1, b1);
+		b1_pressed = b1;
+	}
+	
+	if (b2 != b2_pressed) {
+		mouse_push_event_button(mouse_dev, 2, b2);
+		b1_pressed = b1;
+	}
+	
+	if (dx != 0 || dy != 0)
+		mouse_push_event_move(mouse_dev, dx, dy);
+}
+
+mouse_proto_ops_t adb_proto = {
+	.parse = adb_proto_parse,
+	.init = adb_proto_init
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/proto/mousedev.c
===================================================================
--- uspace/srv/hid/input/proto/mousedev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/srv/hid/input/proto/mousedev.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Mouse device connector controller driver.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <vfs/vfs_sess.h>
+#include <malloc.h>
+#include <async.h>
+#include <errno.h>
+#include <ipc/mouseev.h>
+#include <input.h>
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+
+/** Mousedev softstate */
+typedef struct {
+	/** Link to generic mouse device */
+	mouse_dev_t *mouse_dev;
+	
+	/** Session to mouse device */
+	async_sess_t *sess;
+	
+	/** File descriptor of open mousedev device */
+	int fd;
+} mousedev_t;
+
+static mousedev_t *mousedev_new(mouse_dev_t *mdev)
+{
+	mousedev_t *mousedev = calloc(1, sizeof(mousedev_t));
+	if (mousedev == NULL)
+		return NULL;
+	
+	mousedev->mouse_dev = mdev;
+	mousedev->fd = -1;
+	
+	return mousedev;
+}
+
+static void mousedev_destroy(mousedev_t *mousedev)
+{
+	if (mousedev->sess != NULL)
+		async_hangup(mousedev->sess);
+	
+	if (mousedev->fd >= 0)
+		close(mousedev->fd);
+	
+	free(mousedev);
+}
+
+static void mousedev_callback_conn(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
+{
+	/* Mousedev device structure */
+	mousedev_t *mousedev = (mousedev_t *) arg;
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* XXX Handle hangup */
+			return;
+		}
+		
+		int retval;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case MOUSEEV_MOVE_EVENT:
+			mouse_push_event_move(mousedev->mouse_dev, IPC_GET_ARG1(call),
+			    IPC_GET_ARG2(call));
+			retval = EOK;
+			break;
+		case MOUSEEV_BUTTON_EVENT:
+			mouse_push_event_button(mousedev->mouse_dev, IPC_GET_ARG1(call),
+			    IPC_GET_ARG2(call));
+			retval = EOK;
+			break;
+		default:
+			retval = ENOTSUP;
+			break;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int mousedev_proto_init(mouse_dev_t *mdev)
+{
+	const char *pathname = mdev->dev_path;
+	
+	int fd = open(pathname, O_RDWR);
+	if (fd < 0)
+		return -1;
+	
+	async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd);
+	if (sess == NULL) {
+		printf("%s: Failed starting session with '%s'\n", NAME, pathname);
+		close(fd);
+		return -1;
+	}
+	
+	mousedev_t *mousedev = mousedev_new(mdev);
+	if (mousedev == NULL) {
+		printf("%s: Failed allocating device structure for '%s'.\n",
+		    NAME, pathname);
+		return -1;
+	}
+	
+	mousedev->fd = fd;
+	mousedev->sess = sess;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname);
+		mousedev_destroy(mousedev);
+		return -1;
+	}
+	
+	int rc = async_connect_to_me(exch, 0, 0, 0, mousedev_callback_conn, mousedev);
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		printf("%s: Failed creating callback connection from '%s'.\n",
+		    NAME, pathname);
+		mousedev_destroy(mousedev);
+		return -1;
+	}
+	
+	return 0;
+}
+
+mouse_proto_ops_t mousedev_proto = {
+	.init = mousedev_proto_init
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/proto/ps2.c
===================================================================
--- uspace/srv/hid/input/proto/ps2.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
+++ uspace/srv/hid/input/proto/ps2.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief PS/2 protocol driver.
+ */
+
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+
+#define PS2_MOUSE_OUT_INIT  0xf4
+#define PS2_MOUSE_ACK       0xfa
+
+#define BUFSIZE 3
+
+typedef struct {
+	union {
+		unsigned char data[BUFSIZE];
+		struct {
+			unsigned int leftbtn : 1;
+			unsigned int rightbtn : 1;
+			unsigned int middlebtn : 1;
+			unsigned int isone : 1; /* Always one */
+			unsigned int xsign : 1;
+			unsigned int ysign : 1;
+			unsigned int xovfl : 1;
+			unsigned int yovfl : 1;
+			unsigned char x;
+			unsigned char y;
+		} val;
+	} u;
+} ps2packet_t;
+
+static ps2packet_t buf;
+static unsigned int bufpos;
+static unsigned int leftbtn;
+static unsigned int rightbtn;
+static unsigned int middlebtn;
+
+static mouse_dev_t *mouse_dev;
+
+static int ps2_proto_init(mouse_dev_t *mdev)
+{
+	mouse_dev = mdev;
+	bufpos = 0;
+	leftbtn = 0;
+	rightbtn = 0;
+	
+	mouse_dev->port_ops->write(PS2_MOUSE_OUT_INIT);
+	return 0;
+}
+
+/** Convert 9-bit 2-complement signed number to integer */
+static int bit9toint(int sign, unsigned char data)
+{
+	int tmp;
+	
+	if (!sign)
+		return data;
+	
+	tmp = ((unsigned char) ~data) + 1;
+	return -tmp;
+}
+
+/** Process mouse data */
+static void ps2_proto_parse(sysarg_t data)
+{
+	int x, y;
+	
+	/* Check that we have not lost synchronization */
+	if (bufpos == 0 && !(data & 0x8))
+		return; /* Synchro lost, ignore byte */
+	
+	buf.u.data[bufpos++] = data;
+	if (bufpos == BUFSIZE) {
+		bufpos = 0;
+		
+		if (buf.u.val.leftbtn ^ leftbtn) {
+			leftbtn = buf.u.val.leftbtn;
+			mouse_push_event_button(mouse_dev, 1, leftbtn);
+		}
+		
+		if (buf.u.val.rightbtn ^ rightbtn) {
+			rightbtn = buf.u.val.rightbtn;
+			mouse_push_event_button(mouse_dev, 2, rightbtn);
+		}
+		
+		if (buf.u.val.middlebtn ^ middlebtn) {
+			middlebtn = buf.u.val.middlebtn;
+			mouse_push_event_button(mouse_dev, 3, middlebtn);
+		}
+		
+		x = bit9toint(buf.u.val.xsign, buf.u.val.x);
+		y = -bit9toint(buf.u.val.ysign, buf.u.val.y);
+		
+		if (x != 0 || y != 0)
+			mouse_push_event_move(mouse_dev, x, y);
+	}
+}
+
+mouse_proto_ops_t ps2_proto = {
+	.parse = ps2_proto_parse,
+	.init = ps2_proto_init
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -42,5 +42,5 @@
 #include <io/console.h>
 #include <vfs/vfs.h>
-#include <ipc/mouse.h>
+#include <ipc/mouseev.h>
 #include <async.h>
 #include <async_obsolete.h>
@@ -57,5 +57,5 @@
 
 #define NAME "s3c24ser"
-#define NAMESPACE "hid_in"
+#define NAMESPACE "hid"
 
 static irq_cmd_t ts_irq_cmds[] = {
@@ -284,5 +284,5 @@
 	button = 1;
 	press = 0;
-	async_obsolete_msg_2(ts->client_phone, MEVENT_BUTTON, button, press);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_BUTTON_EVENT, button, press);
 
 	s3c24xx_ts_wait_for_int_mode(ts, updn_down);
@@ -325,6 +325,6 @@
 
 	/* Send notifications to client. */
-	async_obsolete_msg_2(ts->client_phone, MEVENT_MOVE, dx, dy);
-	async_obsolete_msg_2(ts->client_phone, MEVENT_BUTTON, button, press);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_MOVE_EVENT, dx, dy);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_BUTTON_EVENT, button, press);
 
 	ts->last_x = x_pos;
Index: uspace/srv/hw/netif/ne2000/dp8390.c
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hw/netif/ne2000/dp8390.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -483,5 +483,5 @@
 }
 
-static link_t *ne2k_receive(ne2k_t *ne2k)
+static list_t *ne2k_receive(ne2k_t *ne2k)
 {
 	/*
@@ -490,5 +490,5 @@
 	 * frames from the network, but they will be lost.
 	 */
-	link_t *frames = (link_t *) malloc(sizeof(link_t));
+	list_t *frames = (list_t *) malloc(sizeof(list_t));
 	if (frames != NULL)
 		list_initialize(frames);
@@ -567,8 +567,8 @@
 }
 
-link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
+list_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
 {
 	/* List of received frames */
-	link_t *frames = NULL;
+	list_t *frames = NULL;
 	
 	if (isr & (ISR_PTX | ISR_TXE)) {
Index: uspace/srv/hw/netif/ne2000/dp8390.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hw/netif/ne2000/dp8390.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -241,5 +241,5 @@
 extern void ne2k_down(ne2k_t *);
 extern void ne2k_send(ne2k_t *, packet_t *);
-extern link_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
+extern list_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
 
 #endif
Index: uspace/srv/hw/netif/ne2000/ne2000.c
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/hw/netif/ne2000/ne2000.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -168,15 +168,15 @@
 	
 	if (ne2k != NULL) {
-		link_t *frames =
+		list_t *frames =
 		    ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
 		
 		if (frames != NULL) {
 			while (!list_empty(frames)) {
-				frame_t *frame =
-				    list_get_instance(frames->next, frame_t, link);
+				frame_t *frame = list_get_instance(
+				    list_first(frames), frame_t, link);
 				
 				list_remove(&frame->link);
-				nil_received_msg(nil_phone, device_id, frame->packet,
-				    SERVICE_NONE);
+				nil_received_msg(nil_phone, device_id,
+				    frame->packet, SERVICE_NONE);
 				free(frame);
 			}
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -2483,5 +2483,5 @@
 	tcp_globals.net_phone = net_phone;
 	
-	tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
+	tcp_globals.icmp_phone = icmp_connect_module();
 	tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
 	    SERVICE_TCP, tcp_receiver);
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/net/tl/udp/udp.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -396,5 +396,5 @@
 	udp_globals.net_phone = net_phone;
 	
-	udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
+	udp_globals.icmp_phone = icmp_connect_module();
 	
 	udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
Index: uspace/srv/ns/clonable.c
===================================================================
--- uspace/srv/ns/clonable.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/ns/clonable.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -52,5 +52,5 @@
 
 /** List of clonable-service connection requests. */
-static link_t cs_req;
+static list_t cs_req;
 
 int clonable_init(void)
@@ -76,5 +76,8 @@
     ipc_callid_t callid)
 {
-	if (list_empty(&cs_req)) {
+	link_t *req_link;
+
+	req_link = list_first(&cs_req);
+	if (req_link == NULL) {
 		/* There was no pending connection request. */
 		printf("%s: Unexpected clonable server.\n", NAME);
@@ -83,6 +86,6 @@
 	}
 	
-	cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);
-	list_remove(&csr->link);
+	cs_req_t *csr = list_get_instance(req_link, cs_req_t, link);
+	list_remove(req_link);
 	
 	/* Currently we can only handle a single type of clonable service. */
Index: uspace/srv/ns/service.c
===================================================================
--- uspace/srv/ns/service.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/ns/service.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -123,5 +123,5 @@
 } pending_conn_t;
 
-static link_t pending_conn;
+static list_t pending_conn;
 
 int service_init(void)
@@ -141,8 +141,6 @@
 void process_pending_conn(void)
 {
-	link_t *cur;
-	
 loop:
-	for (cur = pending_conn.next; cur != &pending_conn; cur = cur->next) {
+	list_foreach(pending_conn, cur) {
 		pending_conn_t *pr = list_get_instance(cur, pending_conn_t, link);
 		
Index: uspace/srv/ns/task.c
===================================================================
--- uspace/srv/ns/task.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/ns/task.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -189,5 +189,5 @@
 } pending_wait_t;
 
-static link_t pending_wait;
+static list_t pending_wait;
 
 int task_init(void)
@@ -212,9 +212,8 @@
 void process_pending_wait(void)
 {
-	link_t *cur;
 	task_exit_t texit;
 	
 loop:
-	for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) {
+	list_foreach(pending_wait, cur) {
 		pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
 		
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/vfs/vfs.h	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -145,7 +145,7 @@
 extern fibril_mutex_t nodes_mutex;
 
-extern fibril_condvar_t fs_head_cv;
-extern fibril_mutex_t fs_head_lock;
-extern link_t fs_head;		/**< List of registered file systems. */
+extern fibril_condvar_t fs_list_cv;
+extern fibril_mutex_t fs_list_lock;
+extern list_t fs_list;		/**< List of registered file systems. */
 
 extern vfs_pair_t rootfs;	/**< Root file system. */
@@ -158,7 +158,7 @@
 } plb_entry_t;
 
-extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_head. */
+extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_entries. */
 extern uint8_t *plb;		/**< Path Lookup Buffer */
-extern link_t plb_head;		/**< List of active PLB entries. */
+extern list_t plb_entries;	/**< List of active PLB entries. */
 
 #define MAX_MNTOPTS_LEN		256
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/vfs/vfs_lookup.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -50,5 +50,5 @@
 
 FIBRIL_MUTEX_INITIALIZE(plb_mutex);
-LIST_INITIALIZE(plb_head);	/**< PLB entry ring buffer. */
+LIST_INITIALIZE(plb_entries);	/**< PLB entry ring buffer. */
 uint8_t *plb = NULL;
 
@@ -102,12 +102,12 @@
 	size_t last;	/* the last free index */
 
-	if (list_empty(&plb_head)) {
+	if (list_empty(&plb_entries)) {
 		first = 0;
 		last = PLB_SIZE - 1;
 	} else {
-		plb_entry_t *oldest = list_get_instance(plb_head.next,
-		    plb_entry_t, plb_link);
-		plb_entry_t *newest = list_get_instance(plb_head.prev,
-		    plb_entry_t, plb_link);
+		plb_entry_t *oldest = list_get_instance(
+		    list_first(&plb_entries), plb_entry_t, plb_link);
+		plb_entry_t *newest = list_get_instance(
+		    list_last(&plb_entries), plb_entry_t, plb_link);
 
 		first = (newest->index + newest->len) % PLB_SIZE;
@@ -145,5 +145,5 @@
 	 * buffer.
 	 */
-	list_append(&entry.plb_link, &plb_head);
+	list_append(&entry.plb_link, &plb_entries);
 	
 	fibril_mutex_unlock(&plb_mutex);
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/vfs/vfs_ops.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -325,5 +325,5 @@
 	 * This will also give us its file system handle.
 	 */
-	fibril_mutex_lock(&fs_head_lock);
+	fibril_mutex_lock(&fs_list_lock);
 	fs_handle_t fs_handle;
 recheck:
@@ -331,9 +331,9 @@
 	if (!fs_handle) {
 		if (flags & IPC_FLAG_BLOCKING) {
-			fibril_condvar_wait(&fs_head_cv, &fs_head_lock);
+			fibril_condvar_wait(&fs_list_cv, &fs_list_lock);
 			goto recheck;
 		}
 		
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		async_answer_0(callid, ENOENT);
 		async_answer_0(rid, ENOENT);
@@ -343,5 +343,5 @@
 		return;
 	}
-	fibril_mutex_unlock(&fs_head_lock);
+	fibril_mutex_unlock(&fs_list_lock);
 	
 	/* Acknowledge that we know fs_name. */
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 79506d66f2636c3deaec24977cd2aea13dfba7d9)
+++ uspace/srv/vfs/vfs_register.c	(revision cac458feb10a7e040acc99153f39620be18acbdc)
@@ -52,7 +52,7 @@
 #include "vfs.h"
 
-FIBRIL_CONDVAR_INITIALIZE(fs_head_cv);
-FIBRIL_MUTEX_INITIALIZE(fs_head_lock);
-LIST_INITIALIZE(fs_head);
+FIBRIL_CONDVAR_INITIALIZE(fs_list_cv);
+FIBRIL_MUTEX_INITIALIZE(fs_list_lock);
+LIST_INITIALIZE(fs_list);
 
 atomic_t fs_handle_next = {
@@ -149,5 +149,5 @@
 	}
 	
-	fibril_mutex_lock(&fs_head_lock);
+	fibril_mutex_lock(&fs_list_lock);
 	
 	/*
@@ -159,5 +159,5 @@
 		 */
 		dprintf("FS is already registered.\n");
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		free(fs_info);
 		async_answer_0(rid, EEXISTS);
@@ -169,5 +169,5 @@
 	 */
 	dprintf("Inserting FS into the list of registered file systems.\n");
-	list_append(&fs_info->fs_link, &fs_head);
+	list_append(&fs_info->fs_link, &fs_list);
 	
 	/*
@@ -180,5 +180,5 @@
 		dprintf("Callback connection expected\n");
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		free(fs_info);
 		async_answer_0(rid, EINVAL);
@@ -197,5 +197,5 @@
 		dprintf("Unexpected call, method = %d\n", IPC_GET_IMETHOD(call));
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		async_hangup(fs_info->sess);
 		free(fs_info);
@@ -211,5 +211,5 @@
 		dprintf("Client suggests wrong size of PFB, size = %d\n", size);
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		async_hangup(fs_info->sess);
 		free(fs_info);
@@ -235,6 +235,6 @@
 	async_answer_1(rid, EOK, (sysarg_t) fs_info->fs_handle);
 	
-	fibril_condvar_broadcast(&fs_head_cv);
-	fibril_mutex_unlock(&fs_head_lock);
+	fibril_condvar_broadcast(&fs_list_cv);
+	fibril_mutex_unlock(&fs_list_lock);
 	
 	dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
@@ -254,15 +254,14 @@
 	/*
 	 * For now, we don't try to be very clever and very fast.
-	 * We simply lookup the session in the fs_head list and
+	 * We simply lookup the session in fs_list and
 	 * begin an exchange.
 	 */
-	fibril_mutex_lock(&fs_head_lock);
-	
-	link_t *cur;
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+	fibril_mutex_lock(&fs_list_lock);
+	
+	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
 		
 		if (fs->fs_handle == handle) {
-			fibril_mutex_unlock(&fs_head_lock);
+			fibril_mutex_unlock(&fs_list_lock);
 			
 			assert(fs->sess);
@@ -274,5 +273,5 @@
 	}
 	
-	fibril_mutex_unlock(&fs_head_lock);
+	fibril_mutex_unlock(&fs_list_lock);
 	
 	return NULL;
@@ -293,5 +292,5 @@
  * @param name File system name.
  * @param lock If true, the function will lock and unlock the
- *             fs_head_lock.
+ *             fs_list_lock.
  *
  * @return File system handle or zero if file system not found.
@@ -303,8 +302,7 @@
 	
 	if (lock)
-		fibril_mutex_lock(&fs_head_lock);
-	
-	link_t *cur;
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+		fibril_mutex_lock(&fs_list_lock);
+	
+	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
 		if (str_cmp(fs->vfs_info.name, name) == 0) { 
@@ -315,5 +313,5 @@
 	
 	if (lock)
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 	
 	return handle;
@@ -330,8 +328,7 @@
 {
 	vfs_info_t *info = NULL;
-	link_t *cur;
-	
-	fibril_mutex_lock(&fs_head_lock);
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+	
+	fibril_mutex_lock(&fs_list_lock);
+	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
 		if (fs->fs_handle == handle) { 
@@ -340,5 +337,5 @@
 		}
 	}
-	fibril_mutex_unlock(&fs_head_lock);
+	fibril_mutex_unlock(&fs_list_lock);
 	
 	return info;
