Index: uspace/drv/uhci/Makefile
===================================================================
--- uspace/drv/uhci/Makefile	(revision 7972b5174bd5f797d8676d4e3c36a81a8748fd94)
+++ uspace/drv/uhci/Makefile	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -33,5 +33,6 @@
 
 SOURCES = \
-	main.c
+	main.c \
+	transfers.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/uhci/main.c
===================================================================
--- uspace/drv/uhci/main.c	(revision 7972b5174bd5f797d8676d4e3c36a81a8748fd94)
+++ uspace/drv/uhci/main.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -28,50 +28,13 @@
 #include <usb/hcdhubd.h>
 #include <errno.h>
+#include "uhci.h"
 
-static int enqueue_transfer_out(usb_hc_device_t *hc,
-    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *endpoint,
-    void *buffer, size_t size,
-    usb_hcd_transfer_callback_out_t callback, void *arg)
-{
-	printf("UHCI: transfer OUT [%d.%d (%s); %u]\n",
-	    dev->address, endpoint->endpoint,
-	    usb_str_transfer_type(endpoint->transfer_type),
-	    size);
-	return ENOTSUP;
-}
-
-static int enqueue_transfer_setup(usb_hc_device_t *hc,
-    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *endpoint,
-    void *buffer, size_t size,
-    usb_hcd_transfer_callback_out_t callback, void *arg)
-{
-	printf("UHCI: transfer SETUP [%d.%d (%s); %u]\n",
-	    dev->address, endpoint->endpoint,
-	    usb_str_transfer_type(endpoint->transfer_type),
-	    size);
-	return ENOTSUP;
-}
-
-static int enqueue_transfer_in(usb_hc_device_t *hc,
-    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *endpoint,
-    void *buffer, size_t size,
-    usb_hcd_transfer_callback_in_t callback, void *arg)
-{
-	printf("UHCI: transfer IN [%d.%d (%s); %u]\n",
-	    dev->address, endpoint->endpoint,
-	    usb_str_transfer_type(endpoint->transfer_type),
-	    size);
-	return ENOTSUP;
-}
-
-static usb_hcd_transfer_ops_t uhci_transfer_ops = {
-	.transfer_out = enqueue_transfer_out,
-	.transfer_in = enqueue_transfer_in,
-	.transfer_setup = enqueue_transfer_setup
+static device_ops_t uhci_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &uhci_iface,
 };
 
-static int uhci_add_hc(usb_hc_device_t *device)
+static int uhci_add_device(device_t *device)
 {
-	device->transfer_ops = &uhci_transfer_ops;
+	device->ops = &uhci_ops;
 
 	/*
@@ -83,7 +46,11 @@
 }
 
-usb_hc_driver_t uhci_driver = {
-	.name = "uhci",
-	.add_hc = uhci_add_hc
+static driver_ops_t uhci_driver_ops = {
+	.add_device = uhci_add_device,
+};
+
+static driver_t uhci_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_driver_ops
 };
 
@@ -93,5 +60,6 @@
 	 * Do some global initializations.
 	 */
+	sleep(5);
 
-	return usb_hcd_main(&uhci_driver);
+	return driver_main(&uhci_driver);
 }
Index: uspace/drv/uhci/transfers.c
===================================================================
--- uspace/drv/uhci/transfers.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
+++ uspace/drv/uhci/transfers.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+#include <usb/hcdhubd.h>
+#include <errno.h>
+
+#include "uhci.h"
+
+static int enqueue_transfer_out(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    void *buffer, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	printf(NAME ": transfer OUT [%d.%d (%s); %u]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+static int enqueue_transfer_setup(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    void *buffer, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	printf(NAME ": transfer SETUP [%d.%d (%s); %u]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+static int enqueue_transfer_in(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    void *buffer, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	printf(NAME ": transfer IN [%d.%d (%s); %u]\n",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
+	    size);
+
+	return ENOTSUP;
+}
+
+
+static int get_address(device_t *dev, devman_handle_t handle,
+    usb_address_t *address)
+{
+	return ENOTSUP;
+}
+
+static int interrupt_out(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_INTERRUPT,
+	    data, size,
+	    callback, arg);
+}
+
+static int interrupt_in(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_INTERRUPT,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_setup(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_data(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
+	    NULL, 0,
+	    callback, arg);
+}
+
+static int control_read_setup(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_read_data(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_read_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
+	    NULL, 0,
+	    callback, arg);
+}
+
+
+usbhc_iface_t uhci_iface = {
+	.tell_address = get_address,
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+	.control_write_setup = control_write_setup,
+	.control_write_data = control_write_data,
+	.control_write_status = control_write_status,
+	.control_read_setup = control_read_setup,
+	.control_read_data = control_read_data,
+	.control_read_status = control_read_status
+};
Index: uspace/drv/uhci/uhci.h
===================================================================
--- uspace/drv/uhci/uhci.h	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
+++ uspace/drv/uhci/uhci.h	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -0,0 +1,47 @@
+/*
+ * 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 usb
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_UHCI_H
+#define DRV_UHCI_UHCI_H
+
+#include <usbhc_iface.h>
+
+#define NAME "uhci"
+
+usbhc_iface_t uhci_iface;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci/uhci.ma
===================================================================
--- uspace/drv/uhci/uhci.ma	(revision 7972b5174bd5f797d8676d4e3c36a81a8748fd94)
+++ uspace/drv/uhci/uhci.ma	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -1,3 +1,2 @@
 10 pci/ven=8086&dev=7020
-10 usb&hc=uhci
-10 usb&hc=uhci&hub
+
Index: uspace/drv/usbhub/Makefile
===================================================================
--- uspace/drv/usbhub/Makefile	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
+++ uspace/drv/usbhub/Makefile	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -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 $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
+BINARY = usbhub
+
+SOURCES = \
+	main.c \
+	utils.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/usbhub/main.c
===================================================================
--- uspace/drv/usbhub/main.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
+++ uspace/drv/usbhub/main.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -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.
+ */
+#include <usb/usbdrv.h>
+#include <driver.h>
+#include <errno.h>
+#include "usbhub.h"
+
+static driver_ops_t hub_driver_ops = {
+	.add_device = usb_add_hub_device,
+};
+
+static driver_t hub_driver = {
+	.name = "usbhub",
+	.driver_ops = &hub_driver_ops
+};
+
+int main(int argc, char *argv[])
+{
+	return driver_main(&hub_driver);
+}
Index: uspace/drv/usbhub/usbhub.h
===================================================================
--- uspace/drv/usbhub/usbhub.h	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
+++ uspace/drv/usbhub/usbhub.h	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -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 usb
+ * @{
+ */
+/** @file
+ * @brief Hub driver.
+ */
+#ifndef DRV_USBHUB_USBHUB_H
+#define DRV_USBHUB_USBHUB_H
+
+#define NAME "usbhub"
+
+int usb_add_hub_device(device_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/usbhub/usbhub.ma
===================================================================
--- uspace/drv/usbhub/usbhub.ma	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
+++ uspace/drv/usbhub/usbhub.ma	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -0,0 +1,1 @@
+10 usb&hub
Index: uspace/drv/usbhub/utils.c
===================================================================
--- uspace/drv/usbhub/utils.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
+++ uspace/drv/usbhub/utils.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -0,0 +1,249 @@
+/*
+ * 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 libusb usb
+ * @{
+ */
+/** @file
+ * @brief Hub driver.
+ */
+#include <driver.h>
+#include <usb/devreq.h>
+#include <usbhc_iface.h>
+#include <usb/usbdrv.h>
+#include <usb/descriptor.h>
+#include <driver.h>
+#include <bool.h>
+#include <errno.h>
+#include <usb/classes/hub.h>
+#include "usbhub.h"
+
+static void check_hub_changes(void);
+
+size_t USB_HUB_MAX_DESCRIPTOR_SIZE = 71;
+
+//*********************************************
+//
+//  various utils
+//
+//*********************************************
+
+void * usb_serialize_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 / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0);
+	size += 2 * var_size;
+	uint8_t * result = (uint8_t*) malloc(size);
+	//size
+	result[0] = size;
+	//descriptor type
+	result[1] = USB_DESCTYPE_HUB;
+	result[2] = descriptor->ports_count;
+	/// @fixme handling of endianness??
+	result[3] = descriptor->hub_characteristics / 256;
+	result[4] = descriptor->hub_characteristics % 256;
+	result[5] = descriptor->pwr_on_2_good_time;
+	result[6] = descriptor->current_requirement;
+
+	size_t i;
+	for (i = 0; i < var_size; ++i) {
+		result[7 + i] = descriptor->devices_removable[i];
+	}
+	for (i = 0; i < var_size; ++i) {
+		result[7 + var_size + i] = 255;
+	}
+	return result;
+}
+
+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];
+	result->ports_count = sdescriptor[2];
+	/// @fixme handling of endianness??
+	result->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
+	result->pwr_on_2_good_time = sdescriptor[5];
+	result->current_requirement = sdescriptor[6];
+	size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0) ? 1 : 0);
+	result->devices_removable = (uint8_t*) malloc(var_size);
+
+	size_t i;
+	for (i = 0; i < var_size; ++i) {
+		result->devices_removable[i] = sdescriptor[7 + i];
+	}
+	return result;
+}
+
+
+//*********************************************
+//
+//  hub driver code
+//
+//*********************************************
+
+static void set_hub_address(device_t *dev, usb_address_t address);
+
+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));
+
+	return result;
+}
+
+/** Callback when new hub device is detected.
+ *
+ * @param dev New device.
+ * @return Error code.
+ */
+int usb_add_hub_device(device_t *dev) {
+	printf(NAME ": add_hub_device(handle=%d)\n", (int) dev->handle);
+	set_hub_address(dev, 5);
+
+	check_hub_changes();
+
+	/*
+	 * We are some (probably deeply nested) hub.
+	 * Thus, assign our own operations and explore already
+	 * connected devices.
+	 */
+
+	//create the hub structure
+	usb_hcd_hub_info_t * hub_info = usb_create_hub_info(dev);
+	(void)hub_info;
+
+	return EOK;
+	//return ENOTSUP;
+}
+
+/** Sample usage of usb_hc_async functions.
+ * This function sets hub address using standard SET_ADDRESS request.
+ *
+ * @warning This function shall be removed once you are familiar with
+ * the usb_hc_ API.
+ *
+ * @param hc Host controller the hub belongs to.
+ * @param address New hub address.
+ */
+static void set_hub_address(device_t *dev, usb_address_t address) {
+	printf(NAME ": setting hub address to %d\n", address);
+	usb_target_t target = {0, 0};
+	usb_handle_t handle;
+	int rc;
+
+	usb_device_request_setup_packet_t setup_packet = {
+		.request_type = 0,
+		.request = USB_DEVREQ_SET_ADDRESS,
+		.index = 0,
+		.length = 0,
+	};
+	setup_packet.value = address;
+
+	int hc = usb_drv_hc_connect(dev, 0);
+
+	rc = usb_drv_async_control_write_setup(hc, target,
+			&setup_packet, sizeof (setup_packet), &handle);
+	if (rc != EOK) {
+		return;
+	}
+
+	rc = usb_drv_async_wait_for(handle);
+	if (rc != EOK) {
+		return;
+	}
+
+	rc = usb_drv_async_control_write_status(hc, target, &handle);
+	if (rc != EOK) {
+		return;
+	}
+
+	rc = usb_drv_async_wait_for(handle);
+	if (rc != EOK) {
+		return;
+	}
+
+	printf(NAME ": hub address changed\n");
+}
+
+/** Check changes on all known hubs.
+ */
+static void check_hub_changes(void) {
+	/*
+	 * Iterate through all hubs.
+	 */
+	for (; false; ) {
+		/*
+		 * Check status change pipe of this hub.
+		 */
+		usb_target_t target = {
+			.address = 5,
+			.endpoint = 1
+		};
+
+		size_t port_count = 7;
+
+		/*
+		 * Connect to respective HC.
+		 */
+		int hc = usb_drv_hc_connect(NULL, 0);
+		if (hc < 0) {
+			continue;
+		}
+
+		// FIXME: count properly
+		size_t byte_length = (port_count / 8) + 1;
+
+		void *change_bitmap = malloc(byte_length);
+		size_t actual_size;
+		usb_handle_t handle;
+
+		/*
+		 * Send the request.
+		 * FIXME: check returned value for possible errors
+		 */
+		usb_drv_async_interrupt_in(hc, target,
+				change_bitmap, byte_length, &actual_size,
+				&handle);
+
+		usb_drv_async_wait_for(handle);
+
+		/*
+		 * TODO: handle the changes.
+		 */
+
+
+		/*
+		 * Hang-up the HC-connected phone.
+		 */
+		ipc_hangup(hc);
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/vhc/conn.h
===================================================================
--- uspace/drv/vhc/conn.h	(revision 7972b5174bd5f797d8676d4e3c36a81a8748fd94)
+++ uspace/drv/vhc/conn.h	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -38,4 +38,5 @@
 #include <usb/usb.h>
 #include <usb/hcdhubd.h>
+#include <usbhc_iface.h>
 #include "vhcd.h"
 #include "devices.h"
@@ -44,4 +45,5 @@
 
 usb_hcd_transfer_ops_t vhc_transfer_ops;
+usbhc_iface_t vhc_iface;
 
 void default_connection_handler(device_t *, ipc_callid_t, ipc_call_t *);
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision 7972b5174bd5f797d8676d4e3c36a81a8748fd94)
+++ uspace/drv/vhc/connhost.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -43,7 +43,7 @@
 typedef struct {
 	usb_direction_t direction;
-	usb_hcd_transfer_callback_out_t out_callback;
-	usb_hcd_transfer_callback_in_t in_callback;
-	usb_hc_device_t *hc;
+	usbhc_iface_transfer_out_callback_t out_callback;
+	usbhc_iface_transfer_in_callback_t in_callback;
+	device_t *dev;
 	void *arg;
 } transfer_info_t;
@@ -56,10 +56,10 @@
 	switch (transfer->direction) {
 		case USB_DIRECTION_IN:
-			transfer->in_callback(transfer->hc,
+			transfer->in_callback(transfer->dev,
 			    size, outcome,
 			    transfer->arg);
 			break;
 		case USB_DIRECTION_OUT:
-			transfer->out_callback(transfer->hc,
+			transfer->out_callback(transfer->dev,
 			    outcome,
 			    transfer->arg);
@@ -73,5 +73,5 @@
 }
 
-static transfer_info_t *create_transfer_info(usb_hc_device_t *hc,
+static transfer_info_t *create_transfer_info(device_t *dev,
     usb_direction_t direction, void *arg)
 {
@@ -82,27 +82,22 @@
 	transfer->out_callback = NULL;
 	transfer->arg = arg;
-	transfer->hc = hc;
+	transfer->dev = dev;
 
 	return transfer;
 }
 
-static int enqueue_transfer_out(usb_hc_device_t *hc,
-    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *endpoint,
+static int enqueue_transfer_out(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
     void *buffer, size_t size,
-    usb_hcd_transfer_callback_out_t callback, void *arg)
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
 	printf(NAME ": transfer OUT [%d.%d (%s); %u]\n",
-	    dev->address, endpoint->endpoint,
-	    usb_str_transfer_type(endpoint->transfer_type),
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
 	    size);
 
 	transfer_info_t *transfer
-	    = create_transfer_info(hc, USB_DIRECTION_OUT, arg);
+	    = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
 	transfer->out_callback = callback;
-
-	usb_target_t target = {
-		.address = dev->address,
-		.endpoint = endpoint->endpoint
-	};
 
 	hc_add_transaction_to_device(false, target, buffer, size,
@@ -112,22 +107,17 @@
 }
 
-static int enqueue_transfer_setup(usb_hc_device_t *hc,
-    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *endpoint,
+static int enqueue_transfer_setup(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
     void *buffer, size_t size,
-    usb_hcd_transfer_callback_out_t callback, void *arg)
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
 	printf(NAME ": transfer SETUP [%d.%d (%s); %u]\n",
-	    dev->address, endpoint->endpoint,
-	    usb_str_transfer_type(endpoint->transfer_type),
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
 	    size);
 
 	transfer_info_t *transfer
-	    = create_transfer_info(hc, USB_DIRECTION_OUT, arg);
+	    = create_transfer_info(dev, USB_DIRECTION_OUT, arg);
 	transfer->out_callback = callback;
-
-	usb_target_t target = {
-		.address = dev->address,
-		.endpoint = endpoint->endpoint
-	};
 
 	hc_add_transaction_to_device(true, target, buffer, size,
@@ -137,22 +127,17 @@
 }
 
-static int enqueue_transfer_in(usb_hc_device_t *hc,
-    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *endpoint,
+static int enqueue_transfer_in(device_t *dev,
+    usb_target_t target, usb_transfer_type_t transfer_type,
     void *buffer, size_t size,
-    usb_hcd_transfer_callback_in_t callback, void *arg)
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
 	printf(NAME ": transfer IN [%d.%d (%s); %u]\n",
-	    dev->address, endpoint->endpoint,
-	    usb_str_transfer_type(endpoint->transfer_type),
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transfer_type),
 	    size);
 
 	transfer_info_t *transfer
-	    = create_transfer_info(hc, USB_DIRECTION_IN, arg);
+	    = create_transfer_info(dev, USB_DIRECTION_IN, arg);
 	transfer->in_callback = callback;
-
-	usb_target_t target = {
-		.address = dev->address,
-		.endpoint = endpoint->endpoint
-	};
 
 	hc_add_transaction_from_device(target, buffer, size,
@@ -163,8 +148,91 @@
 
 
-usb_hcd_transfer_ops_t vhc_transfer_ops = {
-	.transfer_out = enqueue_transfer_out,
-	.transfer_in = enqueue_transfer_in,
-	.transfer_setup = enqueue_transfer_setup
+static int get_address(device_t *dev, devman_handle_t handle,
+    usb_address_t *address)
+{
+	return ENOTSUP;
+}
+
+static int interrupt_out(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_INTERRUPT,
+	    data, size,
+	    callback, arg);
+}
+
+static int interrupt_in(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_INTERRUPT,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_setup(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_data(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_write_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
+	    NULL, 0,
+	    callback, arg);
+}
+
+static int control_read_setup(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_setup(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_read_data(device_t *dev, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	return enqueue_transfer_in(dev, target, USB_TRANSFER_CONTROL,
+	    data, size,
+	    callback, arg);
+}
+
+static int control_read_status(device_t *dev, usb_target_t target,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	return enqueue_transfer_out(dev, target, USB_TRANSFER_CONTROL,
+	    NULL, 0,
+	    callback, arg);
+}
+
+
+usbhc_iface_t vhc_iface = {
+	.tell_address = get_address,
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+	.control_write_setup = control_write_setup,
+	.control_write_data = control_write_data,
+	.control_write_status = control_write_status,
+	.control_read_setup = control_read_setup,
+	.control_read_data = control_read_data,
+	.control_read_status = control_read_status
 };
 
Index: uspace/drv/vhc/hcd.c
===================================================================
--- uspace/drv/vhc/hcd.c	(revision 7972b5174bd5f797d8676d4e3c36a81a8748fd94)
+++ uspace/drv/vhc/hcd.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -52,7 +52,11 @@
 #include "conn.h"
 
+static device_ops_t vhc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &vhc_iface,
+	.default_handler = default_connection_handler
+};
 
 static int vhc_count = 0;
-static int vhc_add_device(usb_hc_device_t *dev)
+static int vhc_add_device(device_t *dev)
 {
 	/*
@@ -65,6 +69,5 @@
 	vhc_count++;
 
-	dev->transfer_ops = &vhc_transfer_ops;
-	dev->generic->ops->default_handler = default_connection_handler;
+	dev->ops = &vhc_ops;
 
 	/*
@@ -79,7 +82,11 @@
 }
 
-static usb_hc_driver_t vhc_driver = {
+static driver_ops_t vhc_driver_ops = {
+	.add_device = vhc_add_device,
+};
+
+static driver_t vhc_driver = {
 	.name = NAME,
-	.add_hc = &vhc_add_device
+	.driver_ops = &vhc_driver_ops
 };
 
@@ -114,5 +121,5 @@
 	sleep(4);
 
-	return usb_hcd_main(&vhc_driver);
+	return driver_main(&vhc_driver);
 }
 
Index: uspace/drv/vhc/vhc.ma
===================================================================
--- uspace/drv/vhc/vhc.ma	(revision 7972b5174bd5f797d8676d4e3c36a81a8748fd94)
+++ uspace/drv/vhc/vhc.ma	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -1,2 +1,2 @@
 10 usb&hc=vhc
-10 usb&hc=vhc&hub
+
