Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ boot/Makefile.common	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -113,6 +113,5 @@
 	rootvirt \
 	test1 \
-	test2 \
-	vhc
+	test2
 
 RD_DRV_CFG = 
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ boot/arch/amd64/Makefile.inc	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -43,5 +43,6 @@
 	uhci \
 	usbhub \
-	usbkbd
+	usbkbd \
+	vhc
 	
 RD_DRV_CFG += \
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ kernel/generic/include/ipc/ipc.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -43,10 +43,6 @@
 #define IPC_CALL_LEN  6
 
-/** Maximum active async calls per thread */
-#ifdef CONFIG_DEBUG
-	#define IPC_MAX_ASYNC_CALLS  16
-#else
-	#define IPC_MAX_ASYNC_CALLS  4000
-#endif
+/** Maximum active async calls per phone */
+#define IPC_MAX_ASYNC_CALLS  4
 
 /* Flags for calls */
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ kernel/generic/include/proc/task.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -93,9 +93,4 @@
 	phone_t phones[IPC_MAX_PHONES];
 	stats_ipc_t ipc_info;   /**< IPC statistics */
-	/**
-	 * Active asynchronous messages. It is used for limiting uspace to
-	 * certain extent.
-	 */
-	atomic_t active_calls;
 	/** List of synchronous answerboxes. */
 	link_t sync_box_head;
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ kernel/generic/src/ipc/ipc.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -655,12 +655,4 @@
 		    (call->flags & IPC_CALL_NOTIF));
 		
-		/*
-		 * Record the receipt of this call in the current task's counter
-		 * of active calls. IPC_M_PHONE_HUNGUP calls do not contribute
-		 * to this counter so do not record answers to them either.
-		 */
-		if (!(call->flags & IPC_CALL_DISCARD_ANSWER))
-			atomic_dec(&TASK->active_calls);
-		
 		ipc_call_free(call);
 	}
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ kernel/generic/src/ipc/sysipc.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -644,15 +644,15 @@
 }
 
-/** Check that the task did not exceed the allowed limit of asynchronous calls.
- *
+/** Check that the task did not exceed the allowed limit of asynchronous calls
+ * made over a phone.
+ *
+ * @param phone Phone to check the limit against. 
  * @return 0 if limit not reached or -1 if limit exceeded.
  *
  */
-static int check_call_limit(void)
-{
-	if (atomic_preinc(&TASK->active_calls) > IPC_MAX_ASYNC_CALLS) {
-		atomic_dec(&TASK->active_calls);
+static int check_call_limit(phone_t *phone)
+{
+	if (atomic_get(&phone->active_calls) >= IPC_MAX_ASYNC_CALLS)
 		return -1;
-	}
 	
 	return 0;
@@ -680,10 +680,10 @@
     unative_t arg1, unative_t arg2, unative_t arg3, unative_t arg4)
 {
-	if (check_call_limit())
-		return IPC_CALLRET_TEMPORARY;
-	
 	phone_t *phone;
 	if (phone_get(phoneid, &phone) != EOK)
 		return IPC_CALLRET_FATAL;
+
+	if (check_call_limit(phone))
+		return IPC_CALLRET_TEMPORARY;
 	
 	call_t *call = ipc_call_alloc(0);
@@ -720,10 +720,10 @@
 unative_t sys_ipc_call_async_slow(unative_t phoneid, ipc_data_t *data)
 {
-	if (check_call_limit())
-		return IPC_CALLRET_TEMPORARY;
-	
 	phone_t *phone;
 	if (phone_get(phoneid, &phone) != EOK)
 		return IPC_CALLRET_FATAL;
+
+	if (check_call_limit(phone))
+		return IPC_CALLRET_TEMPORARY;
 
 	call_t *call = ipc_call_alloc(0);
@@ -1046,11 +1046,4 @@
 			ipc_call_free(call);
 			goto restart;
-		} else {
-			/*
-			 * Decrement the counter of active calls only if the
-			 * call is not an answer to IPC_M_PHONE_HUNGUP,
-			 * which doesn't contribute to the counter.
-			 */
-			atomic_dec(&TASK->active_calls);
 		}
 		
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ kernel/generic/src/proc/task.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -151,5 +151,4 @@
 	atomic_set(&task->refcount, 0);
 	atomic_set(&task->lifecount, 0);
-	atomic_set(&task->active_calls, 0);
 	
 	irq_spinlock_initialize(&task->lock, "task_t_lock");
@@ -478,6 +477,6 @@
 #ifdef __32_BITS__
 	if (*additional)
-		printf("%-8" PRIu64 " %9" PRIua " %7" PRIua, task->taskid,
-		    atomic_get(&task->refcount), atomic_get(&task->active_calls));
+		printf("%-8" PRIu64 " %9" PRIua, task->taskid,
+		    atomic_get(&task->refcount));
 	else
 		printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %10p %10p"
@@ -490,7 +489,6 @@
 	if (*additional)
 		printf("%-8" PRIu64 " %9" PRIu64 "%c %9" PRIu64 "%c "
-		    "%9" PRIua " %7" PRIua,
-		    task->taskid, ucycles, usuffix, kcycles, ksuffix,
-		    atomic_get(&task->refcount), atomic_get(&task->active_calls));
+		    "%9" PRIua, task->taskid, ucycles, usuffix, kcycles,
+		    ksuffix, atomic_get(&task->refcount));
 	else
 		printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %18p %18p\n",
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/Makefile	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -90,6 +90,5 @@
 	drv/rootvirt \
 	drv/test1 \
-	drv/test2 \
-	drv/vhc
+	drv/test2
 
 ## Networking
@@ -118,4 +117,8 @@
 	DIRS += drv/isa
 	DIRS += drv/ns8250
+	DIRS += drv/uhci
+	DIRS += drv/usbhub
+	DIRS += drv/usbkbd
+	DIRS += drv/vhc
 endif
 
@@ -128,4 +131,5 @@
 	DIRS += drv/usbhub
 	DIRS += drv/usbkbd
+	DIRS += drv/vhc
 endif
 
Index: uspace/drv/uhci/transfers.c
===================================================================
--- uspace/drv/uhci/transfers.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/drv/uhci/transfers.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -36,5 +36,5 @@
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-	printf(NAME ": transfer OUT [%d.%d (%s); %u]\n",
+	printf(NAME ": transfer OUT [%d.%d (%s); %zu]\n",
 	    target.address, target.endpoint,
 	    usb_str_transfer_type(transfer_type),
@@ -49,5 +49,5 @@
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
-	printf(NAME ": transfer SETUP [%d.%d (%s); %u]\n",
+	printf(NAME ": transfer SETUP [%d.%d (%s); %zu]\n",
 	    target.address, target.endpoint,
 	    usb_str_transfer_type(transfer_type),
@@ -62,5 +62,5 @@
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
-	printf(NAME ": transfer IN [%d.%d (%s); %u]\n",
+	printf(NAME ": transfer IN [%d.%d (%s); %zu]\n",
 	    target.address, target.endpoint,
 	    usb_str_transfer_type(transfer_type),
Index: uspace/drv/usbhub/main.c
===================================================================
--- uspace/drv/usbhub/main.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/drv/usbhub/main.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -30,4 +30,8 @@
 #include <errno.h>
 #include "usbhub.h"
+#include "usbhub_private.h"
+
+
+usb_general_list_t usb_hub_list;
 
 static driver_ops_t hub_driver_ops = {
@@ -42,4 +46,5 @@
 int main(int argc, char *argv[])
 {
+	usb_lst_init(&usb_hub_list);
 	return driver_main(&hub_driver);
 }
Index: uspace/drv/usbhub/port_status.h
===================================================================
--- uspace/drv/usbhub/port_status.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
+++ uspace/drv/usbhub/port_status.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -0,0 +1,303 @@
+/*
+ * 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.
+ */
+
+#ifndef PORT_STATUS_H
+#define	PORT_STATUS_H
+
+#include <bool.h>
+#include <sys/types.h>
+#include <usb/devreq.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;
+
+/**
+ * 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_STATE;
+	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 =
+		usb_new(usb_device_request_setup_packet_t);
+	usb_hub_set_port_status_request(result,port);
+	return result;
+}
+
+
+/**
+ * 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 =
+		usb_new(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 =
+		usb_new(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 =
+		usb_new(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;
+}
+
+/** get i`th bit of port status */
+static inline bool usb_port_get_bit(usb_port_status_t * status, int idx)
+{
+	return (((*status)>>(idx))%2);
+}
+
+/** set i`th bit of port status */
+static inline void usb_port_set_bit(
+	usb_port_status_t * status, int idx, bool value)
+{
+	(*status) = value?
+		               ((*status)|(1<<(idx))):
+		               ((*status)&(~(1<<(idx))));
+}
+
+//device connnected on port
+static inline bool usb_port_dev_connected(usb_port_status_t * status){
+	return usb_port_get_bit(status,0);
+}
+
+static inline void usb_port_set_dev_connected(usb_port_status_t * status,bool connected){
+	usb_port_set_bit(status,0,connected);
+}
+
+//port enabled
+static inline bool usb_port_enabled(usb_port_status_t * status){
+	return usb_port_get_bit(status,1);
+}
+
+static inline void usb_port_set_enabled(usb_port_status_t * status,bool enabled){
+	usb_port_set_bit(status,1,enabled);
+}
+
+//port suspended
+static inline bool usb_port_suspended(usb_port_status_t * status){
+	return usb_port_get_bit(status,2);
+}
+
+static inline void usb_port_set_suspended(usb_port_status_t * status,bool suspended){
+	usb_port_set_bit(status,2,suspended);
+}
+
+//over currect
+static inline bool usb_port_over_current(usb_port_status_t * status){
+	return usb_port_get_bit(status,3);
+}
+
+static inline void usb_port_set_over_current(usb_port_status_t * status,bool value){
+	usb_port_set_bit(status,3,value);
+}
+
+//port reset
+static inline bool usb_port_reset(usb_port_status_t * status){
+	return usb_port_get_bit(status,4);
+}
+
+static inline void usb_port_set_reset(usb_port_status_t * status,bool value){
+	usb_port_set_bit(status,4,value);
+}
+
+//powered
+static inline bool usb_port_powered(usb_port_status_t * status){
+	return usb_port_get_bit(status,8);
+}
+
+static inline void usb_port_set_powered(usb_port_status_t * status,bool powered){
+	usb_port_set_bit(status,8,powered);
+}
+
+//low speed device attached
+static inline bool usb_port_low_speed(usb_port_status_t * status){
+	return usb_port_get_bit(status,9);
+}
+
+static inline void usb_port_set_low_speed(usb_port_status_t * status,bool low_speed){
+	usb_port_set_bit(status,9,low_speed);
+}
+
+
+//connect change
+static inline bool usb_port_connect_change(usb_port_status_t * status){
+	return usb_port_get_bit(status,16);
+}
+
+static inline void usb_port_set_connect_change(usb_port_status_t * status,bool change){
+	usb_port_set_bit(status,16,change);
+}
+
+//port enable change
+static inline bool usb_port_enabled_change(usb_port_status_t * status){
+	return usb_port_get_bit(status,17);
+}
+
+static inline void usb_port_set_enabled_change(usb_port_status_t * status,bool change){
+	usb_port_set_bit(status,17,change);
+}
+
+//suspend change
+static inline bool usb_port_suspend_change(usb_port_status_t * status){
+	return usb_port_get_bit(status,18);
+}
+
+static inline void usb_port_set_suspend_change(usb_port_status_t * status,bool change){
+	usb_port_set_bit(status,18,change);
+}
+
+//over current change
+static inline bool usb_port_overcurrent_change(usb_port_status_t * status){
+	return usb_port_get_bit(status,19);
+}
+
+static inline void usb_port_set_overcurrent_change(usb_port_status_t * status,bool change){
+	usb_port_set_bit(status,19,change);
+}
+
+//reset change
+static inline bool usb_port_reset_completed(usb_port_status_t * status){
+	return usb_port_get_bit(status,20);
+}
+
+static inline void usb_port_set_reset_completed(usb_port_status_t * status,bool completed){
+	usb_port_set_bit(status,20,completed);
+}
+
+
+
+#endif	/* PORT_STATUS_H */
+
Index: uspace/drv/usbhub/usbhub.h
===================================================================
--- uspace/drv/usbhub/usbhub.h	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/drv/usbhub/usbhub.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -38,4 +38,16 @@
 #define NAME "usbhub"
 
+#include "usb/hcdhubd.h"
+
+
+
+/** Information about attached hub. */
+typedef struct {
+	/** Number of ports. */
+	int port_count;
+	/** General device info. */
+	usb_hcd_attached_device_info_t * device;
+} usb_hub_info_t;
+
 int usb_add_hub_device(device_t *);
 
Index: uspace/drv/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/usbhub/usbhub_private.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
+++ uspace/drv/usbhub/usbhub_private.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -0,0 +1,190 @@
+/*
+ * 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 usb
+ * @{
+ */
+/** @file
+ * @brief Hub driver.
+ */
+
+#ifndef USBHUB_PRIVATE_H
+#define	USBHUB_PRIVATE_H
+
+#include "usbhub.h"
+#include <adt/list.h>
+#include <bool.h>
+#include <driver.h>
+#include <usb/usb.h>
+#include <usb/classes/hub.h>
+#include <usb/devreq.h>
+
+//************
+//
+// convenience define for malloc
+//
+//************
+#define usb_new(type) (type*)malloc(sizeof(type))
+
+
+//************
+//
+// My private list implementation; I did not like the original helenos list
+//
+// This one does not depend on the structure of stored data
+//
+//************
+
+/** general list structure */
+
+
+typedef struct usb_general_list{
+	void * data;
+	struct usb_general_list * prev, * next;
+} usb_general_list_t;
+
+/** create head of usb general list */
+usb_general_list_t * usb_lst_create(void);
+
+/** initialize head of usb general list */
+void usb_lst_init(usb_general_list_t * lst);
+
+
+/** is the list empty? */
+static inline bool usb_lst_empty(usb_general_list_t * lst){
+	return lst?(lst->next==lst):true;
+}
+
+/** append data behind item */
+void usb_lst_append(usb_general_list_t * lst, void * data);
+
+/** prepend data beore item */
+void usb_lst_prepend(usb_general_list_t * lst, void * data);
+
+/** remove list item from list */
+void usb_lst_remove(usb_general_list_t * item);
+
+/** get data o specified type from list item */
+#define usb_lst_get_data(item, type)  (type *) (item->data)
+
+/** get usb_hub_info_t data from list item */
+static inline usb_hub_info_t * usb_hub_lst_get_data(usb_general_list_t * item) {
+	return usb_lst_get_data(item,usb_hub_info_t);
+}
+
+/**
+ * @brief create hub structure instance
+ *
+ * Set the address and port count information most importantly.
+ *
+ * @param device
+ * @param hc host controller phone
+ * @return
+ */
+usb_hub_info_t * usb_create_hub_info(device_t * device, int hc);
+
+/** list of hubs maanged by this driver */
+extern usb_general_list_t usb_hub_list;
+
+
+/**
+ * @brief perform complete control read transaction
+ *
+ * manages all three steps of transaction: setup, read and finalize
+ * @param phone
+ * @param target
+ * @param request request for data
+ * @param rcvd_buffer received data
+ * @param rcvd_size
+ * @param actual_size actual size of received data
+ * @return error code
+ */
+int usb_drv_sync_control_read(
+    int phone, usb_target_t target,
+    usb_device_request_setup_packet_t * request,
+    void * rcvd_buffer, size_t rcvd_size, size_t * actual_size
+);
+
+/**
+ * @brief perform complete control write transaction
+ *
+ * maanges all three steps of transaction: setup, write and finalize
+ * @param phone
+ * @param target
+ * @param request request to send data
+ * @param sent_buffer
+ * @param sent_size
+ * @return error code
+ */
+int usb_drv_sync_control_write(
+    int phone, usb_target_t target,
+    usb_device_request_setup_packet_t * request,
+    void * sent_buffer, size_t sent_size
+);
+
+
+/**
+ * set the device request to be a set address request
+ * @param request
+ * @param addr
+ * \TODO this will be obsolete see usb/dev_req.h
+ */
+static inline void usb_hub_set_set_address_request(
+usb_device_request_setup_packet_t * request, uint16_t addr
+){
+	request->index = 0;
+	request->request_type = 0;/// \TODO this is not very nice sollution, we ned constant
+	request->request = USB_DEVREQ_SET_ADDRESS;
+	request->value = addr;
+	request->length = 0;
+}
+
+/**
+ * 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;
+}
+
+
+
+#endif	/* USBHUB_PRIVATE_H */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhub/utils.c
===================================================================
--- uspace/drv/usbhub/utils.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/drv/usbhub/utils.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -43,4 +43,7 @@
 #include <usb/classes/hub.h>
 #include "usbhub.h"
+#include "usbhub_private.h"
+#include "port_status.h"
+#include <usb/devreq.h>
 
 static void check_hub_changes(void);
@@ -53,4 +56,6 @@
 //
 //*********************************************
+
+//hub descriptor utils
 
 void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor) {
@@ -84,7 +89,13 @@
 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) {
 	uint8_t * sdescriptor = (uint8_t*) serialized_descriptor;
-	if (sdescriptor[1] != USB_DESCTYPE_HUB) return NULL;
-	usb_hub_descriptor_t * result = (usb_hub_descriptor_t*) malloc(sizeof (usb_hub_descriptor_t));
-	//uint8_t size = sdescriptor[0];
+
+	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
+		printf("[usb_hub] wrong descriptor %x\n",sdescriptor[1]);
+		return NULL;
+	}
+
+	usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t);
+	
+
 	result->ports_count = sdescriptor[2];
 	/// @fixme handling of endianness??
@@ -94,5 +105,5 @@
 	size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0) ? 1 : 0);
 	result->devices_removable = (uint8_t*) malloc(var_size);
-
+	//printf("[usb_hub] getting removable devices data \n");
 	size_t i;
 	for (i = 0; i < var_size; ++i) {
@@ -102,13 +113,249 @@
 }
 
+//control transactions
+
+int usb_drv_sync_control_read(
+		int phone, usb_target_t target,
+		usb_device_request_setup_packet_t * request,
+		void * rcvd_buffer, size_t rcvd_size, size_t * actual_size
+		) {
+	usb_handle_t handle;
+	int opResult;
+	//setup
+	opResult = usb_drv_async_control_read_setup(phone, target,
+			request, sizeof (usb_device_request_setup_packet_t),
+			&handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	opResult = usb_drv_async_wait_for(handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	//read
+	opResult = usb_drv_async_control_read_data(phone, target,
+			rcvd_buffer, rcvd_size, actual_size,
+			&handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	opResult = usb_drv_async_wait_for(handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	//finalize
+	opResult = usb_drv_async_control_read_status(phone, target,
+			&handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	opResult = usb_drv_async_wait_for(handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	return EOK;
+}
+
+int usb_drv_sync_control_write(
+		int phone, usb_target_t target,
+		usb_device_request_setup_packet_t * request,
+		void * sent_buffer, size_t sent_size
+		) {
+	usb_handle_t handle;
+	int opResult;
+	//setup
+	opResult = usb_drv_async_control_write_setup(phone, target,
+			request, sizeof (usb_device_request_setup_packet_t),
+			&handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	opResult = usb_drv_async_wait_for(handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	//write
+	opResult = usb_drv_async_control_write_data(phone, target,
+			sent_buffer, sent_size,
+			&handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	opResult = usb_drv_async_wait_for(handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	//finalize
+	opResult = usb_drv_async_control_write_status(phone, target,
+			&handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	opResult = usb_drv_async_wait_for(handle);
+	if (opResult != EOK) {
+		return opResult;
+	}
+	return EOK;
+}
+
+//list implementation
+
+usb_general_list_t * usb_lst_create(void) {
+	usb_general_list_t* result = usb_new(usb_general_list_t);
+	usb_lst_init(result);
+	return result;
+}
+
+void usb_lst_init(usb_general_list_t * lst) {
+	lst->prev = lst;
+	lst->next = lst;
+	lst->data = NULL;
+}
+
+void usb_lst_prepend(usb_general_list_t* item, void* data) {
+	usb_general_list_t* appended = usb_new(usb_general_list_t);
+	appended->data = data;
+	appended->next = item;
+	appended->prev = item->prev;
+	item->prev->next = appended;
+	item->prev = appended;
+}
+
+void usb_lst_append(usb_general_list_t* item, void* data) {
+	usb_general_list_t* appended = usb_new(usb_general_list_t);
+	appended->data = data;
+	appended->next = item->next;
+	appended->prev = item;
+	item->next->prev = appended;
+	item->next = appended;
+}
+
+void usb_lst_remove(usb_general_list_t* item) {
+	item->next->prev = item->prev;
+	item->prev->next = item->next;
+}
+
+static void usb_hub_test_port_status(void) {
+	printf("[usb_hub] -------------port status test---------\n");
+	usb_port_status_t status = 0;
+
+	//printf("original status %d (should be 0)\n",(uint32_t)status);
+	usb_port_set_bit(&status, 1, 1);
+	//printf("%d =?= 2\n",(uint32_t)status);
+	if (status != 2) {
+		printf("[usb_port_status] test failed: wrong set of bit 1\n");
+		return;
+	}
+	usb_port_set_bit(&status, 3, 1);
+	if (status != 10) {
+		printf("[usb_port_status] test failed: wrong set of bit 3\n");
+		return;
+	}
+
+	usb_port_set_bit(&status, 15, 1);
+	if (status != 10 + (1 << 15)) {
+		printf("[usb_port_status] test failed: wrong set of bit 15\n");
+		return;
+	}
+	usb_port_set_bit(&status, 1, 0);
+	if (status != 8 + (1 << 15)) {
+		printf("[usb_port_status] test failed: wrong unset of bit 1\n");
+		return;
+	}
+	int i;
+	for (i = 0; i < 32; ++i) {
+		if (i == 3 || i == 15) {
+			if (!usb_port_get_bit(&status, i)) {
+				printf("[usb_port_status] test failed: wrong bit at %d\n", i);
+			}
+		} else {
+			if (usb_port_get_bit(&status, i)) {
+				printf("[usb_port_status] test failed: wrong bit at %d\n", i);
+			}
+		}
+	}
+
+	printf("test ok\n");
+
+
+	//printf("%d =?= 10\n",(uint32_t)status);
+
+	//printf("this should be 0: %d \n",usb_port_get_bit(&status,0));
+	//printf("this should be 1: %d \n",usb_port_get_bit(&status,1));
+	//printf("this should be 0: %d \n",usb_port_get_bit(&status,2));
+	//printf("this should be 1: %d \n",usb_port_get_bit(&status,3));
+	//printf("this should be 0: %d \n",usb_port_get_bit(&status,4));
+
+
+
+
+}
 
 //*********************************************
 //
-//  hub driver code
+//  hub driver code, initialization
 //
 //*********************************************
 
-usb_hcd_hub_info_t * usb_create_hub_info(device_t * device) {
-	usb_hcd_hub_info_t* result = (usb_hcd_hub_info_t*) malloc(sizeof (usb_hcd_hub_info_t));
+usb_hub_info_t * usb_create_hub_info(device_t * device, int hc) {
+	usb_hub_info_t* result = usb_new(usb_hub_info_t);
+	//result->device = device;
+	result->port_count = -1;
+
+
+	//printf("[usb_hub] phone to hc = %d\n", hc);
+	if (hc < 0) {
+		return result;
+	}
+	//get some hub info
+	usb_address_t addr = usb_drv_get_my_address(hc, device);
+	printf("[usb_hub] addres of newly created hub = %d\n", addr);
+	/*if(addr<0){
+		//return result;
+		
+	}*/
+
+	result->device = usb_new(usb_hcd_attached_device_info_t);
+	result->device->address = addr;
+
+	// get hub descriptor
+	usb_target_t target;
+	target.address = addr;
+	target.endpoint = 0;
+	usb_device_request_setup_packet_t request;
+	//printf("[usb_hub] creating descriptor request\n");
+	usb_hub_set_descriptor_request(&request);
+
+	//printf("[usb_hub] creating serialized descriptor\n");
+	void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
+	usb_hub_descriptor_t * descriptor;
+	size_t received_size;
+	int opResult;
+	//printf("[usb_hub] starting control transaction\n");
+	opResult = usb_drv_sync_control_read(
+			hc, target, &request, serialized_descriptor,
+			USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
+	if (opResult != EOK) {
+		printf("[usb_hub] failed when receiving hub descriptor, badcode = %d\n",opResult);
+		///\TODO memory leak will occur here!
+		return result;
+	}
+	//printf("[usb_hub] deserializing descriptor\n");
+	descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
+	if(descriptor==NULL){
+		printf("[usb_hub] could not deserialize descriptor \n");
+		result->port_count = 1;///\TODO this code is only for debug!!!
+		return result;
+	}
+	//printf("[usb_hub] setting port count to %d\n",descriptor->ports_count);
+	result->port_count = descriptor->ports_count;
+	//printf("[usb_hub] freeing data\n");
+	free(serialized_descriptor);
+	free(descriptor->devices_removable);
+	free(descriptor);
+
+	//finish
+
+	printf("[usb_hub] hub info created\n");
 
 	return result;
@@ -122,6 +369,5 @@
 int usb_add_hub_device(device_t *dev) {
 	printf(NAME ": add_hub_device(handle=%d)\n", (int) dev->handle);
-
-	check_hub_changes();
+	printf("[usb_hub] hub device\n");
 
 	/*
@@ -132,6 +378,38 @@
 
 	//create the hub structure
-	usb_hcd_hub_info_t * hub_info = usb_create_hub_info(dev);
-	(void)hub_info;
+	//get hc connection
+	/// \TODO correct params
+	int hc = usb_drv_hc_connect(dev, 0);
+
+	usb_hub_info_t * hub_info = usb_create_hub_info(dev, hc);
+	int port;
+	int opResult;
+	usb_device_request_setup_packet_t request;
+	usb_target_t target;
+	target.address = hub_info->device->address;
+	target.endpoint = 0;
+	for (port = 0; port < hub_info->port_count; ++port) {
+		usb_hub_set_power_port_request(&request, port);
+		opResult = usb_drv_sync_control_write(hc, target, &request, NULL, 0);
+		if (opResult != EOK) {
+			printf("[usb_hub]something went wrong when setting hub`s %dth port\n", port);
+		}
+	}
+	//ports powered, hub seems to be enabled
+
+	ipc_hangup(hc);
+
+	//add the hub to list
+	usb_lst_append(&usb_hub_list, hub_info);
+	printf("[usb_hub] hub info added to list\n");
+	//(void)hub_info;
+	check_hub_changes();
+
+	/// \TODO start the check loop, if not already started...
+
+	//this is just a test for port status bitmap type
+	usb_hub_test_port_status();
+
+	printf("[usb_hub] hub dev added\n");
 
 	return EOK;
@@ -139,4 +417,169 @@
 }
 
+//*********************************************
+//
+//  hub driver code, main loop
+//
+//*********************************************
+
+/**
+ * reset the port with new device and reserve the default address
+ * @param hc
+ * @param port
+ * @param target
+ */
+
+static void usb_hub_init_add_device(int hc, uint16_t port, usb_target_t target) {
+	usb_device_request_setup_packet_t request;
+	int opResult;
+	printf("[usb_hub] some connection changed\n");
+
+	opResult = usb_drv_reserve_default_address(hc);
+	if (opResult != EOK) {
+		printf("[usb_hub] cannot assign default address, it is probably used\n");
+		return;
+	}
+	//reset port
+	usb_hub_set_reset_port_request(&request, port);
+	opResult = usb_drv_sync_control_write(
+			hc, target,
+			&request,
+			NULL, 0
+			);
+	if (opResult != EOK) {
+		//continue;
+		printf("[usb_hub] something went wrong when reseting a port\n");
+	}
+}
+
+/**
+ * finalize adding new device after port reset
+ * @param hc
+ * @param port
+ * @param target
+ */
+static void usb_hub_finalize_add_device(
+		int hc, uint16_t port, usb_target_t target) {
+
+	usb_device_request_setup_packet_t request;
+	int opResult;
+	printf("[usb_hub] finalizing add device\n");
+	usb_address_t new_device_address =
+			usb_drv_request_address(hc);
+	usb_hub_set_set_address_request
+			(&request, new_device_address);
+	opResult = usb_drv_sync_control_write(
+			hc, target,
+			&request,
+			NULL, 0
+			);
+	if (opResult != EOK) {
+		printf("[usb_hub] could not set address for new device\n");
+		//will retry later...
+		return;
+	}
+	usb_drv_release_default_address(hc);
+
+
+	/// \TODO driver work
+	//add_child_device.....
+}
+
+/**
+ * unregister device address in hc, close the port
+ * @param hc
+ * @param port
+ * @param target
+ */
+static void usb_hub_removed_device(int hc, uint16_t port, usb_target_t target) {
+	usb_device_request_setup_packet_t request;
+	int opResult;
+	//disable port
+	usb_hub_set_disable_port_request(&request, port);
+	opResult = usb_drv_sync_control_write(
+			hc, target,
+			&request,
+			NULL, 0
+			);
+	if (opResult != EOK) {
+		//continue;
+		printf("[usb_hub] something went wrong when disabling a port\n");
+	}
+	//remove device
+	//close address
+	//
+
+	///\TODO this code is not complete
+}
+
+/**
+ * process interrupts on given hub port
+ * @param hc
+ * @param port
+ * @param target
+ */
+static void usb_hub_process_interrupt(int hc, uint16_t port, usb_target_t target) {
+	printf("[usb_hub] interrupt at port %d\n", port);
+	//determine type of change
+	usb_port_status_t status;
+	size_t rcvd_size;
+	usb_device_request_setup_packet_t request;
+	int opResult;
+	usb_hub_set_port_status_request(&request, port);
+
+	opResult = usb_drv_sync_control_read(
+			hc, target,
+			&request,
+			&status, 4, &rcvd_size
+			);
+	if (opResult != EOK) {
+		printf("[usb_hub] ERROR: could not get port status\n");
+		return;
+	}
+	if (rcvd_size != sizeof (usb_port_status_t)) {
+		printf("[usb_hub] ERROR: received status has incorrect size\n");
+		return;
+	}
+	//something connected/disconnected
+	if (usb_port_connect_change(&status)) {
+		if (usb_port_dev_connected(&status)) {
+			printf("[usb_hub] some connection changed\n");
+			usb_hub_init_add_device(hc, port, target);
+		} else {
+			usb_hub_removed_device(hc, port, target);
+		}
+	}
+	//port reset
+	if (usb_port_reset_completed(&status)) {
+		printf("[usb_hub] finalizing add device\n");
+		if (usb_port_enabled(&status)) {
+			usb_hub_finalize_add_device(hc, port, target);
+		} else {
+			printf("[usb_hub] ERROR: port reset, but port still not enabled\n");
+		}
+	}
+
+	usb_port_set_connect_change(&status, false);
+	usb_port_set_reset(&status, false);
+	usb_port_set_reset_completed(&status, false);
+	usb_port_set_dev_connected(&status, false);
+	if (status) {
+		printf("[usb_hub]there was some unsupported change on port\n");
+	}
+	/// \TODO handle other changes
+	/// \TODO debug log for various situations
+
+
+
+	/*
+	//configure device
+	usb_drv_reserve_default_address(hc);
+
+	usb_address_t new_device_address = usb_drv_request_address(hc);
+
+
+	usb_drv_release_default_address(hc);
+	 * */
+}
 
 /** Check changes on all known hubs.
@@ -146,12 +589,19 @@
 	 * Iterate through all hubs.
 	 */
-	for (; false; ) {
+	usb_general_list_t * lst_item;
+	for (lst_item = usb_hub_list.next;
+			lst_item != &usb_hub_list;
+			lst_item = lst_item->next) {
+		printf("[usb_hub] checking hub changes\n");
 		/*
 		 * Check status change pipe of this hub.
 		 */
+
 		usb_target_t target = {
 			.address = 5,
 			.endpoint = 1
 		};
+		/// \TODO uncomment once it works correctly
+		//target.address = usb_create_hub_info(lst_item)->device->address;
 
 		size_t port_count = 7;
@@ -160,4 +610,7 @@
 		 * Connect to respective HC.
 		 */
+		/// \FIXME this is incorrect code: here
+		/// must be used particular device instead of NULL
+		//which one?
 		int hc = usb_drv_hc_connect(NULL, 0);
 		if (hc < 0) {
@@ -174,11 +627,23 @@
 		/*
 		 * Send the request.
-		 * FIXME: check returned value for possible errors
-		 */
-		usb_drv_async_interrupt_in(hc, target,
+		 */
+		int opResult = usb_drv_async_interrupt_in(hc, target,
 				change_bitmap, byte_length, &actual_size,
 				&handle);
 
 		usb_drv_async_wait_for(handle);
+
+		if (opResult != EOK) {
+			printf("[usb_hub] something went wrong while getting status of hub\n");
+			continue;
+		}
+		unsigned int port;
+		for (port = 0; port < port_count; ++port) {
+			bool interrupt = (((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
+			if (interrupt) {
+				usb_hub_process_interrupt(hc, port, target);
+			}
+		}
+
 
 		/*
Index: uspace/drv/vhc/hubops.c
===================================================================
--- uspace/drv/vhc/hubops.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/drv/vhc/hubops.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -195,7 +195,16 @@
 }
 
-static int get_hub_descriptor(uint8_t descriptor_type,
-    uint8_t descriptor_index, uint16_t length)
-{
+static int get_hub_descriptor(struct usbvirt_device *dev,
+    uint8_t descriptor_index,
+    uint8_t descriptor_type, uint16_t length)
+{
+	if (descriptor_type == USB_DESCTYPE_HUB) {
+		int rc = dev->control_transfer_reply(dev, 0,
+		    &hub_descriptor, hub_descriptor.length);
+
+		return rc;
+
+	}
+
 	return ENOTSUP;
 }
@@ -313,5 +322,5 @@
 			
 		case USB_HUB_REQUEST_GET_DESCRIPTOR:
-			return get_hub_descriptor(request->value_low,
+			return get_hub_descriptor(dev, request->value_low,
 			    request->value_high, request->length);
 			
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -177,4 +177,5 @@
 
 /** @brief hub class request codes*/
+/// \TODO these are duplicit to standart descriptors
 typedef enum {
     /**  */
@@ -213,11 +214,4 @@
 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * sdescriptor);
 
-/**
- * @brief create hub structure instance
- * 
- * @param device
- * @return
- */
-usb_hcd_hub_info_t * usb_create_hub_info(device_t * device);
 
 
Index: uspace/lib/usb/include/usb/hcdhubd.h
===================================================================
--- uspace/lib/usb/include/usb/hcdhubd.h	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/lib/usb/include/usb/hcdhubd.h	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -65,13 +65,4 @@
 } usb_hcd_attached_device_info_t;
 
-/** Information about attached hub. */
-typedef struct {
-	/** Number of ports. */
-	size_t port_count;
-	/** General device info. */
-	usb_hcd_attached_device_info_t *device;
-	/** Link to other hubs. */
-	link_t link;
-} usb_hcd_hub_info_t;
 
 /** Host controller device. */
Index: uspace/lib/usb/src/usbdrv.c
===================================================================
--- uspace/lib/usb/src/usbdrv.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/lib/usb/src/usbdrv.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -36,4 +36,5 @@
 #include <usbhc_iface.h>
 #include <errno.h>
+#include <str_error.h>
 
 /** Information about pending transaction on HC. */
@@ -90,8 +91,10 @@
 {
 	ipcarg_t address;
-	int rc = async_req_1_1(phone, IPC_M_USBHC_GET_ADDRESS,
+	int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_GET_ADDRESS,
 	    dev->handle, &address);
 
 	if (rc != EOK) {
+		printf("usb_drv_get_my_address over %d failed: %s\n", phone, str_error(rc));
 		return rc;
 	}
@@ -107,5 +110,6 @@
 int usb_drv_reserve_default_address(int phone)
 {
-	return async_req_0_0(phone, IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS);
+	return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS);
 }
 
@@ -117,5 +121,6 @@
 int usb_drv_release_default_address(int phone)
 {
-	return async_req_0_0(phone, IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
+	return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
 }
 
@@ -128,5 +133,6 @@
 {
 	ipcarg_t address;
-	int rc = async_req_0_1(phone, IPC_M_USBHC_REQUEST_ADDRESS, &address);
+	int rc = async_req_1_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_REQUEST_ADDRESS, &address);
 	if (rc != EOK) {
 		return rc;
@@ -146,5 +152,6 @@
     devman_handle_t handle)
 {
-	int rc = async_req_2_0(phone, IPC_M_USBHC_BIND_ADDRESS,
+	int rc = async_req_3_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_BIND_ADDRESS,
 	    address, handle);
 
@@ -160,5 +167,6 @@
 int usb_drv_release_address(int phone, usb_address_t address)
 {
-	return async_req_1_0(phone, IPC_M_USBHC_RELEASE_ADDRESS, address);
+	return async_req_2_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_ADDRESS, address);
 }
 
Index: uspace/lib/usbvirt/transaction.c
===================================================================
--- uspace/lib/usbvirt/transaction.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/lib/usbvirt/transaction.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -184,4 +184,6 @@
 				actual_size = size;
 			}
+			device->lib_debug(device, 1, USBVIRT_DEBUGTAG_TRANSACTION,
+			    "in transaction: will copy %zu bytes", actual_size);
 			if (actual_size > 0) {
 				memcpy(buffer, transfer->data, actual_size);
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision cf978f2e8306ba4f632bf50ec92e1cc612e36083)
+++ uspace/srv/devman/devman.c	(revision dad6e8a74bbeccd0dabf53711be221f488b1c176)
@@ -686,6 +686,4 @@
 }
 
-static FIBRIL_MUTEX_INITIALIZE(add_device_guard);
-
 /** Pass a device to running driver.
  *
@@ -695,6 +693,4 @@
 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)
 {
-	fibril_mutex_lock(&add_device_guard);
-
 	/*
 	 * We do not expect to have driver's mutex locked as we do not
@@ -727,6 +723,4 @@
 	/* Wait for answer from the driver. */
 	async_wait_for(req, &rc);
-
-	fibril_mutex_unlock(&add_device_guard);
 
 	switch(rc) {
