Index: uspace/drv/ohci/Makefile
===================================================================
--- uspace/drv/ohci/Makefile	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/Makefile	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -37,4 +37,5 @@
 	main.c \
 	hc.c \
+	ohci.c \
 	root_hub.c \
 	pci.c
Index: uspace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/hc.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -39,5 +39,4 @@
 #include <usb/debug.h>
 #include <usb/usb.h>
-#include <usb/hub.h>
 #include <usb/ddfiface.h>
 #include <usb/usbdevice.h>
@@ -45,6 +44,31 @@
 #include "hc.h"
 
-static int dummy_reset(int foo, void *arg);
 static int interrupt_emulator(hc_t *instance);
+/*----------------------------------------------------------------------------*/
+int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
+{
+	assert(instance);
+	assert(hub_fun);
+
+	usb_address_t hub_address =
+	    device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
+	instance->rh.address = hub_address;
+	usb_device_keeper_bind(
+	    &instance->manager, hub_address, hub_fun->handle);
+
+	char *match_str = NULL;
+	int ret = asprintf(&match_str, "usb&mid");
+	ret = (match_str == NULL) ? ret : EOK;
+	if (ret < 0) {
+		usb_log_error("Failed to create root hub match-id string.\n");
+		return ret;
+	}
+
+	ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
+	if (ret != EOK) {
+		usb_log_error("Failed add create root hub match-id.\n");
+	}
+	return ret;
+}
 /*----------------------------------------------------------------------------*/
 int hc_init(hc_t *instance, ddf_fun_t *fun, ddf_dev_t *dev,
@@ -68,44 +92,7 @@
 	}
 
+	rh_init(&instance->rh, dev, instance->registers);
 
-	rh_init(&instance->rh, dev, instance->registers);
 	/* TODO: implement */
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-int hc_register_hub(hc_t *instance)
-{
-	async_usleep(1000000);
-#define CHECK_RET_RETURN(ret, msg...) \
-	if (ret != EOK) { \
-		usb_log_error(msg); \
-		return ret; \
-	} else (void)0
-	assert(instance);
-	assert(instance->ddf_instance);
-	assert(instance->ddf_instance->handle);
-	ddf_dev_t *dev = instance->rh.device;
-	int ret = EOK;
-
-	usb_hc_connection_t conn;
-	ret =
-	    usb_hc_connection_initialize(&conn, instance->ddf_instance->handle);
-	CHECK_RET_RETURN(ret, "Failed to initialize hc connection.\n");
-
-	ret = usb_hc_connection_open(&conn);
-	CHECK_RET_RETURN(ret, "Failed to open hc connection.\n");
-
-	usb_address_t address;
-	devman_handle_t handle;
-	ret = usb_hc_new_device_wrapper(dev, &conn, USB_SPEED_FULL, dummy_reset,
-	    0, instance, &address, &handle, NULL, NULL, NULL);
-	if (ret != EOK) {
-		usb_log_error("Failed to add rh device.\n");
-		instance->rh.address = -1;
-		return ret;
-	}
-
-	ret = usb_hc_connection_close(&conn);
-	CHECK_RET_RETURN(ret, "Failed to close hc connection.\n");
 	return EOK;
 }
@@ -134,13 +121,5 @@
 }
 /*----------------------------------------------------------------------------*/
-static int dummy_reset(int foo, void *arg)
-{
-	hc_t *hc = (hc_t*)arg;
-	assert(hc);
-	hc->rh.address = 0;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int interrupt_emulator(hc_t *instance)
+int interrupt_emulator(hc_t *instance)
 {
 	assert(instance);
Index: uspace/drv/ohci/hc.h
===================================================================
--- uspace/drv/ohci/hc.h	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/hc.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -57,8 +57,8 @@
 } hc_t;
 
+int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
+
 int hc_init(hc_t *instance, ddf_fun_t *fun, ddf_dev_t *dev,
      uintptr_t regs, size_t reg_size, bool interrupts);
-
-int hc_register_hub(hc_t *instance);
 
 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
Index: uspace/drv/ohci/iface.h
===================================================================
--- uspace/drv/ohci/iface.h	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/iface.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -33,10 +33,8 @@
  * Common OHCI definitions.
  */
-#ifndef DRV_OHCI_OHCI_H
-#define DRV_OHCI_OHCI_H
+#ifndef DRV_OHCI_IFACE_H
+#define DRV_OHCI_IFACE_H
 
 #include <usbhc_iface.h>
-
-#define NAME "ohci"
 
 extern usbhc_iface_t hc_iface;
Index: uspace/drv/ohci/main.c
===================================================================
--- uspace/drv/ohci/main.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/main.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -34,57 +34,14 @@
  */
 #include <ddf/driver.h>
-#include <ddf/interrupt.h>
-#include <device/hw_res.h>
 #include <errno.h>
 #include <str_error.h>
 
-#include <usb_iface.h>
-#include <usb/ddfiface.h>
 #include <usb/debug.h>
 
-#include "pci.h"
-#include "iface.h"
-#include "hc.h"
+#include "ohci.h"
+
+#define NAME "ohci"
 
 static int ohci_add_device(ddf_dev_t *device);
-static int get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
-{
-	assert(handle);
-  assert(fun != NULL);
-
-  *handle = fun->handle;
-  return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int get_address(
-    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
-{
-	assert(fun);
-	usb_device_keeper_t *manager = &fun_to_hc(fun)->manager;
-  usb_address_t addr = usb_device_keeper_find(manager, handle);
-  if (addr < 0) {
-    return addr;
-  }
-
-  if (address != NULL) {
-    *address = addr;
-  }
-
-  return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** IRQ handling callback, identifies device
- *
- * @param[in] dev DDF instance of the device to use.
- * @param[in] iid (Unused).
- * @param[in] call Pointer to the call that represents interrupt.
- */
-static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
-{
-	assert(dev);
-	hc_t *hc = (hc_t*)dev->driver_data;
-	assert(hc);
-	hc_interrupt(hc, 0);
-}
 /*----------------------------------------------------------------------------*/
 static driver_ops_t ohci_driver_ops = {
@@ -97,14 +54,4 @@
 };
 /*----------------------------------------------------------------------------*/
-static usb_iface_t hc_usb_iface = {
-	.get_address = get_address,
-	.get_hc_handle = get_hc_handle,
-};
-/*----------------------------------------------------------------------------*/
-static ddf_dev_ops_t hc_ops = {
-	.interfaces[USB_DEV_IFACE] = &hc_usb_iface,
-	.interfaces[USBHC_DEV_IFACE] = &hc_iface,
-};
-/*----------------------------------------------------------------------------*/
 /** Initializes a new ddf driver instance of OHCI hcd.
  *
@@ -112,86 +59,25 @@
  * @return Error code.
  */
-static int ohci_add_device(ddf_dev_t *device)
+int ohci_add_device(ddf_dev_t *device)
 {
+	usb_log_debug("ohci_add_device() called\n");
 	assert(device);
-#define CHECK_RET_RETURN(ret, message...) \
-if (ret != EOK) { \
-	usb_log_error(message); \
-	return ret; \
-}
-
-	uintptr_t mem_reg_base = 0;
-	size_t mem_reg_size = 0;
-	int irq = 0;
-
-	int ret =
-	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to get memory addresses:.\n", ret, device->handle);
-	usb_log_info("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n",
-	    mem_reg_base, mem_reg_size, irq);
-
-	ret = pci_disable_legacy(device);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret));
-
-	hc_t *hcd = malloc(sizeof(hc_t));
-	if (hcd == NULL) {
+	ohci_t *ohci = malloc(sizeof(ohci_t));
+	if (ohci == NULL) {
 		usb_log_error("Failed to allocate OHCI driver.\n");
 		return ENOMEM;
 	}
 
-	ddf_fun_t *hc_fun = ddf_fun_create(device, fun_exposed, "ohci-hc");
-	if (hc_fun == NULL) {
-		usb_log_error("Failed to create OHCI function.\n");
-		free(hcd);
-		return ENOMEM;
-	}
-
-
-	bool interrupts = false;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, " \
-	    "falling back to polling.\n");
-#else
-	ret = pci_enable_interrupts(device);
+	int ret = ohci_init(ohci, device);
 	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
+		usb_log_error("Failed to initialize OHCI driver: %s.\n",
 		    str_error(ret));
-		usb_log_info("HW interrupts not available, " \
-		    "falling back to polling.\n");
-	} else {
-		usb_log_debug("Hw interrupts enabled.\n");
-		interrupts = true;
-	}
-#endif
-
-	ret = hc_init(hcd, hc_fun, device, mem_reg_base, mem_reg_size, interrupts);
-	if (ret != EOK) {
-		usb_log_error("Failed to initialize OHCI driver.\n");
-		free(hcd);
 		return ret;
 	}
+	device->driver_data = ohci;
 
-	ret = register_interrupt_handler(device, irq, irq_handler, NULL);
-
-	hc_fun->ops = &hc_ops;
-	ret = ddf_fun_bind(hc_fun);
-	if (ret != EOK) {
-		usb_log_error("Failed to bind OHCI function.\n");
-		ddf_fun_destroy(hc_fun);
-		free(hcd);
-		return ret;
-	}
-	hc_fun->driver_data = hcd;
-
-	fid_t later = fibril_create((int(*)(void*))hc_register_hub, hcd);
-	fibril_add_ready(later);
-
-	usb_log_info("Controlling new OHCI device `%s' (handle %llu).\n",
-	    device->name, device->handle);
+	usb_log_info("Controlling new OHCI device `%s'.\n", device->name);
 
 	return EOK;
-#undef CHECK_RET_RETURN
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/ohci/ohci.c
===================================================================
--- uspace/drv/ohci/ohci.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
+++ uspace/drv/ohci/ohci.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/interrupt.h>
+#include <usb_iface.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "ohci.h"
+#include "iface.h"
+#include "pci.h"
+
+/** IRQ handling callback, identifies device
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
+static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	assert(dev);
+	hc_t *hc = &((ohci_t*)dev->driver_data)->hc;
+	uint16_t status = IPC_GET_ARG1(*call);
+	assert(hc);
+	hc_interrupt(hc, status);
+}
+/*----------------------------------------------------------------------------*/
+/** Get address of the device identified by handle.
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
+static int usb_iface_get_address(
+    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
+{
+	assert(fun);
+	usb_device_keeper_t *manager = &((ohci_t*)fun->dev->driver_data)->hc.manager;
+
+	usb_address_t addr = usb_device_keeper_find(manager, handle);
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Gets handle of the respective hc (this device, hc function).
+ *
+ * @param[in] root_hub_fun Root hub function seeking hc handle.
+ * @param[out] handle Place to write the handle.
+ * @return Error code.
+ */
+static int usb_iface_get_hc_handle(
+    ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(handle);
+	ddf_fun_t *hc_fun = ((ohci_t*)fun->dev->driver_data)->hc_fun;
+	assert(hc_fun != NULL);
+
+	*handle = hc_fun->handle;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** This iface is generic for both RH and HC. */
+static usb_iface_t usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle,
+	.get_address = usb_iface_get_address
+};
+/*----------------------------------------------------------------------------*/
+static ddf_dev_ops_t hc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
+};
+/*----------------------------------------------------------------------------*/
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface,
+};
+/*----------------------------------------------------------------------------*/
+/** Initialize hc and rh ddf structures and their respective drivers.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] device DDF instance of the device to use.
+ *
+ * This function does all the preparatory work for hc and rh drivers:
+ *  - gets device hw resources
+ *  - disables UHCI legacy support
+ *  - asks for interrupt
+ *  - registers interrupt handler
+ */
+int ohci_init(ohci_t *instance, ddf_dev_t *device)
+{
+	assert(instance);
+	instance->hc_fun = NULL;
+	instance->rh_fun = NULL;
+#define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	if (instance->hc_fun) \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) \
+		ddf_fun_destroy(instance->rh_fun); \
+	return ret; \
+}
+
+	uintptr_t mem_reg_base = 0;
+	size_t mem_reg_size = 0;
+	int irq = 0;
+
+	int ret =
+	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to get memory addresses:.\n", ret, device->handle);
+	usb_log_debug("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n",
+	    mem_reg_base, mem_reg_size, irq);
+
+	ret = pci_disable_legacy(device);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
+
+	bool interrupts = false;
+#ifdef CONFIG_USBHC_NO_INTERRUPTS
+	usb_log_warning("Interrupts disabled in OS config, " \
+	    "falling back to polling.\n");
+#else
+	ret = pci_enable_interrupts(device);
+	if (ret != EOK) {
+		usb_log_warning("Failed to enable interrupts: %s.\n",
+		    str_error(ret));
+		usb_log_info("HW interrupts not available, " \
+		    "falling back to polling.\n");
+	} else {
+		usb_log_debug("Hw interrupts enabled.\n");
+		interrupts = true;
+	}
+#endif
+
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci-hc");
+	ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to create HC function.\n", ret);
+
+	ret = hc_init(&instance->hc, instance->hc_fun, device,
+	    mem_reg_base, mem_reg_size, interrupts);
+	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init ohci-hcd.\n", ret);
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to bind UHCI device function: %s.\n",
+	    ret, str_error(ret));
+#undef CHECK_RET_HC_RETURN
+
+#define CHECK_RET_FINI_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	if (instance->hc_fun) \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) \
+		ddf_fun_destroy(instance->rh_fun); \
+	hc_fini(&instance->hc); \
+	return ret; \
+}
+
+	/* It does no harm if we register this on polling */
+	ret = register_interrupt_handler(device, irq, irq_handler, NULL);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to register interrupt handler.\n", ret);
+
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci-rh");
+	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to create root hub function.\n", ret);
+
+	hc_register_hub(&instance->hc, instance->rh_fun);
+
+	instance->rh_fun->ops = &rh_ops;
+	instance->rh_fun->driver_data = NULL;
+	ret = ddf_fun_bind(instance->rh_fun);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to register UHCI root hub.\n", ret);
+
+	return EOK;
+#undef CHECK_RET_FINI_RETURN
+}
+/**
+ * @}
+ */
Index: uspace/drv/ohci/ohci.h
===================================================================
--- uspace/drv/ohci/ohci.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
+++ uspace/drv/ohci/ohci.h	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver main structure for both host controller and root-hub.
+ */
+#ifndef DRV_OHCI_OHCI_H
+#define DRV_OHCI_OHCI_H
+#include <ddi.h>
+#include <ddf/driver.h>
+
+#include "hc.h"
+#include "root_hub.h"
+
+typedef struct ohci {
+	ddf_fun_t *hc_fun;
+	ddf_fun_t *rh_fun;
+
+	hc_t hc;
+	rh_t rh;
+} ohci_t;
+
+int ohci_init(ohci_t *instance, ddf_dev_t *device);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision f3da9b2e921b69b298ae508bcdad240890b6a9f2)
+++ uspace/drv/ohci/root_hub.c	(revision aee6c733e31cce6abb49278bbf6be466ed901caf)
@@ -43,4 +43,57 @@
 #include <usb/classes/hub.h>
 
+static const usb_standard_device_descriptor_t ohci_rh_device_descriptor =
+{
+		.configuration_count = 1,
+		.descriptor_type = USB_DESCTYPE_DEVICE,
+		.device_class = USB_CLASS_HUB,
+		.device_protocol = 0,
+		.device_subclass = 0,
+		.device_version = 0,
+		.length = sizeof(usb_standard_device_descriptor_t),
+		/// \TODO this value is guessed
+		.max_packet_size = 8,
+		.vendor_id = 0x16db,
+		.product_id = 0x0001,
+		/// \TODO these values migt be different
+		.str_serial_number = 0,
+		.usb_spec_version = 0,
+};
+
+static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =
+{
+	/// \TODO some values are default or guessed
+	.attributes = 1<<7,
+	.configuration_number = 1,
+	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
+	.interface_count = 1,
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.max_power = 100,
+	.str_configuration = 0,
+};
+
+static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor =
+{
+	.alternate_setting = 0,
+	.descriptor_type = USB_DESCTYPE_INTERFACE,
+	.endpoint_count = 1,
+	.interface_class = USB_CLASS_HUB,
+	/// \TODO is this correct?
+	.interface_number = 1,
+	.interface_protocol = 0,
+	.interface_subclass = 0,
+	.length = sizeof(usb_standard_interface_descriptor_t),
+	.str_interface = 0,
+};
+
+static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor =
+{
+	.attributes = USB_TRANSFER_INTERRUPT,
+	.descriptor_type = USB_DESCTYPE_ENDPOINT,
+	.endpoint_address = 1 + (1<<7),
+	.length = sizeof(usb_standard_endpoint_descriptor_t),
+	.max_packet_size = 8,
+	.poll_interval = 255,
+};
 
 /** Root hub initialization
@@ -330,7 +383,70 @@
 			(usb_device_request_setup_packet_t*)request->setup_buffer;
 	size_t size;
-	void * result_descriptor;
-	uint16_t setup_request_value = setup_request->value_high;
+	const void * result_descriptor = NULL;
+	const uint16_t setup_request_value = setup_request->value_high;
 			//(setup_request->value_low << 8);
+#if 0
+	bool del = false;
+	//this code was merged from development and has to be reviewed
+	switch (setup_request_value)
+	{
+	case USB_DESCTYPE_HUB: {
+		uint8_t * descriptor;
+		usb_create_serialized_hub_descriptor(
+		    instance, &descriptor, &size);
+		result_descriptor = descriptor;
+		break;
+	}
+	case USB_DESCTYPE_DEVICE: {
+		usb_log_debug("USB_DESCTYPE_DEVICE\n");
+		result_descriptor = &ohci_rh_device_descriptor;
+		size = sizeof(ohci_rh_device_descriptor);
+		break;
+	}
+	case USB_DESCTYPE_CONFIGURATION: {
+		usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
+		usb_standard_configuration_descriptor_t * descriptor =
+				malloc(sizeof(usb_standard_configuration_descriptor_t));
+		memcpy(descriptor, &ohci_rh_conf_descriptor,
+		    sizeof(usb_standard_configuration_descriptor_t));
+		/// \TODO should this include device descriptor?
+		const size_t hub_descriptor_size = 7 +
+				2* (instance->port_count / 8 +
+				((instance->port_count % 8 > 0) ? 1 : 0));
+		descriptor->total_length =
+				sizeof(usb_standard_configuration_descriptor_t)+
+				sizeof(usb_standard_endpoint_descriptor_t)+
+				sizeof(usb_standard_interface_descriptor_t)+
+				hub_descriptor_size;
+		result_descriptor = descriptor;
+		size = sizeof(usb_standard_configuration_descriptor_t);
+		del = true;
+		break;
+	}
+	case USB_DESCTYPE_INTERFACE: {
+		usb_log_debug("USB_DESCTYPE_INTERFACE\n");
+		result_descriptor = &ohci_rh_iface_descriptor;
+		size = sizeof(ohci_rh_iface_descriptor);
+		break;
+	}
+	case USB_DESCTYPE_ENDPOINT: {
+		usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
+		result_descriptor = &ohci_rh_ep_descriptor;
+		size = sizeof(ohci_rh_ep_descriptor);
+		break;
+	}
+	default: {
+		usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);
+		usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",
+				setup_request->request_type,
+				setup_request->request,
+				setup_request_value,
+				setup_request->index,
+				setup_request->length
+				);
+		return EINVAL;
+	}
+	}
+#endif
 	if(setup_request_value == USB_DESCTYPE_HUB){
 		usb_log_debug("USB_DESCTYPE_HUB\n");
@@ -378,5 +494,6 @@
 	request->transfered_size = size;
 	memcpy(request->buffer,result_descriptor,size);
-	free(result_descriptor);
+	if (result_descriptor)
+		free(result_descriptor);
 	return EOK;
 }
