Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 62c96615022e186f351a9820811f6cf99a926a52)
+++ uspace/Makefile	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -118,4 +118,5 @@
 	DIRS += drv/ns8250
 	DIRS += drv/uhci
+	DIRS += drv/usbhub
 	DIRS += drv/usbkbd
 endif
Index: uspace/drv/uhci/Makefile
===================================================================
--- uspace/drv/uhci/Makefile	(revision 62c96615022e186f351a9820811f6cf99a926a52)
+++ 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 62c96615022e186f351a9820811f6cf99a926a52)
+++ 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 62c96615022e186f351a9820811f6cf99a926a52)
+++ 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 62c96615022e186f351a9820811f6cf99a926a52)
+++ 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 62c96615022e186f351a9820811f6cf99a926a52)
+++ 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 62c96615022e186f351a9820811f6cf99a926a52)
+++ 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 62c96615022e186f351a9820811f6cf99a926a52)
+++ uspace/drv/vhc/vhc.ma	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -1,2 +1,2 @@
 10 usb&hc=vhc
-10 usb&hc=vhc&hub
+
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 62c96615022e186f351a9820811f6cf99a926a52)
+++ uspace/lib/usb/Makefile	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -35,5 +35,4 @@
 	src/hcdhubd.c \
 	src/hcdrv.c \
-	src/hubdrv.c \
 	src/localdrv.c \
 	src/remotedrv.c \
Index: uspace/lib/usb/include/usb/hcdhubd.h
===================================================================
--- uspace/lib/usb/include/usb/hcdhubd.h	(revision 62c96615022e186f351a9820811f6cf99a926a52)
+++ uspace/lib/usb/include/usb/hcdhubd.h	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -146,5 +146,5 @@
 
 int usb_hcd_main(usb_hc_driver_t *);
-int usb_hcd_add_root_hub(usb_hc_device_t *dev);
+int usb_hcd_add_root_hub(device_t *dev);
 
 
Index: uspace/lib/usb/src/hcdhubd.c
===================================================================
--- uspace/lib/usb/src/hcdhubd.c	(revision 62c96615022e186f351a9820811f6cf99a926a52)
+++ uspace/lib/usb/src/hcdhubd.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -51,20 +51,5 @@
  */
 static int add_device(device_t *dev) {
-	bool is_hc = str_cmp(dev->name, USB_HUB_DEVICE_NAME) != 0;
-	printf("%s: add_device(name=\"%s\")\n", hc_driver->name, dev->name);
-
-	if (is_hc) {
-		/*
-		 * We are the HC itself.
-		 */
-		return usb_add_hc_device(dev);
-	} else {
-		/*
-		 * We are some (maybe deeply nested) hub.
-		 * Thus, assign our own operations and explore already
-		 * connected devices.
-		 */
-		return usb_add_hub_device(dev);
-	}
+	return ENOTSUP;
 }
 
@@ -105,13 +90,13 @@
  * @return Error code.
  */
-int usb_hcd_add_root_hub(usb_hc_device_t *dev)
+int usb_hcd_add_root_hub(device_t *dev)
 {
 	char *id;
-	int rc = asprintf(&id, "usb&hc=%s&hub", hc_driver->name);
+	int rc = asprintf(&id, "usb&hub");
 	if (rc <= 0) {
 		return rc;
 	}
 
-	rc = usb_hc_add_child_device(dev->generic, USB_HUB_DEVICE_NAME, id, true);
+	rc = usb_hc_add_child_device(dev, USB_HUB_DEVICE_NAME, id, true);
 	if (rc != EOK) {
 		free(id);
Index: uspace/lib/usb/src/hcdhubd_private.h
===================================================================
--- uspace/lib/usb/src/hcdhubd_private.h	(revision 62c96615022e186f351a9820811f6cf99a926a52)
+++ uspace/lib/usb/src/hcdhubd_private.h	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -46,5 +46,4 @@
 usb_address_t usb_get_address_by_handle(devman_handle_t);
 int usb_add_hc_device(device_t *);
-int usb_add_hub_device(device_t *);
 
 #endif
Index: uspace/lib/usb/src/hcdrv.c
===================================================================
--- uspace/lib/usb/src/hcdrv.c	(revision 62c96615022e186f351a9820811f6cf99a926a52)
+++ uspace/lib/usb/src/hcdrv.c	(revision 43178271ecca79c7c77563dbd2a252faa9b39f82)
@@ -47,6 +47,11 @@
 LIST_INITIALIZE(hc_list);
 
+/* Fake driver to have the name item initialized. */
+static usb_hc_driver_t hc_driver_fake = {
+	.name = "HCD",
+};
+
 /** Our HC driver. */
-usb_hc_driver_t *hc_driver = NULL;
+usb_hc_driver_t *hc_driver = &hc_driver_fake;
 
 static device_ops_t usb_device_ops = {
@@ -71,4 +76,5 @@
 int usb_add_hc_device(device_t *dev)
 {
+	return ENOTSUP;
 	usb_hc_device_t *hc_dev = usb_hc_device_create(dev);
 
Index: uspace/lib/usb/src/hubdrv.c
===================================================================
--- uspace/lib/usb/src/hubdrv.c	(revision 62c96615022e186f351a9820811f6cf99a926a52)
+++ 	(revision )
@@ -1,278 +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 libusb usb
- * @{
- */
-/** @file
- * @brief Hub driver.
- */
-#include <usb/hcdhubd.h>
-#include <usb/devreq.h>
-#include <usbhc_iface.h>
-#include <usb/descriptor.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-#include <usb/classes/hub.h>
-#include "hcdhubd_private.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(usb_hc_device_t *hc, 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));
-	//get parent device
-	/// @TODO this code is not correct
-	device_t * my_hcd = device;
-	while (my_hcd->parent)
-		my_hcd = my_hcd->parent;
-	//dev->
-	printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name);
-	//we add the hub into the first hc
-	//link_t *link_hc = hc_list.next;
-	//usb_hc_device_t *hc = list_get_instance(link_hc,
-	//		usb_hc_device_t, link);
-	//must get generic device info
-
-
-	return result;
-}
-
-/** Callback when new hub device is detected.
- *
- * @param dev New device.
- * @return Error code.
- */
-int usb_add_hub_device(device_t *dev) {
-	usb_hc_device_t *hc = list_get_instance(hc_list.next, usb_hc_device_t, link);
-	set_hub_address(hc, 5);
-
-	check_hub_changes();
-
-	/*
-	 * We are some (probably deeply nested) hub.
-	 * Thus, assign our own operations and explore already
-	 * connected devices.
-	 */
-	//insert hub into list
-	//find owner hcd
-	device_t * my_hcd = dev;
-	while (my_hcd->parent)
-		my_hcd = my_hcd->parent;
-	//dev->
-	printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name);
-	my_hcd = dev;
-	while (my_hcd->parent)
-		my_hcd = my_hcd->parent;
-	//dev->
-
-	printf("%s: owner hcd found: %s\n", hc_driver->name, my_hcd->name);
-
-	//create the hub structure
-	usb_hcd_hub_info_t * hub_info = usb_create_hub_info(dev);
-
-
-	//append into the list
-	//we add the hub into the first hc
-	list_append(&hub_info->link, &hc->hubs);
-
-
-
-	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(usb_hc_device_t *hc, usb_address_t address) {
-	printf("%s: setting hub address to %d\n", hc->generic->name, 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;
-
-	rc = usb_hc_async_control_write_setup(hc, target,
-			&setup_packet, sizeof (setup_packet), &handle);
-	if (rc != EOK) {
-		return;
-	}
-
-	rc = usb_hc_async_wait_for(handle);
-	if (rc != EOK) {
-		return;
-	}
-
-	rc = usb_hc_async_control_write_status(hc, target, &handle);
-	if (rc != EOK) {
-		return;
-	}
-
-	rc = usb_hc_async_wait_for(handle);
-	if (rc != EOK) {
-		return;
-	}
-
-	printf("%s: hub address changed\n", hc->generic->name);
-}
-
-/** Check changes on all known hubs.
- */
-static void check_hub_changes(void) {
-	/*
-	 * Iterate through all HCs.
-	 */
-	link_t *link_hc;
-	for (link_hc = hc_list.next;
-			link_hc != &hc_list;
-			link_hc = link_hc->next) {
-		usb_hc_device_t *hc = list_get_instance(link_hc,
-				usb_hc_device_t, link);
-		/*
-		 * Iterate through all their hubs.
-		 */
-		link_t *link_hub;
-		for (link_hub = hc->hubs.next;
-				link_hub != &hc->hubs;
-				link_hub = link_hub->next) {
-			usb_hcd_hub_info_t *hub = list_get_instance(link_hub,
-					usb_hcd_hub_info_t, link);
-
-			/*
-			 * Check status change pipe of this hub.
-			 */
-			usb_target_t target = {
-				.address = hub->device->address,
-				.endpoint = 1
-			};
-
-			// FIXME: count properly
-			size_t byte_length = (hub->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_hc_async_interrupt_in(hc, target,
-					change_bitmap, byte_length, &actual_size,
-					&handle);
-
-			usb_hc_async_wait_for(handle);
-
-			/*
-			 * TODO: handle the changes.
-			 */
-		}
-	}
-}
-
-/**
- * @}
- */
