Index: uspace/drv/ehci-hcd/Makefile
===================================================================
--- uspace/drv/ehci-hcd/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ehci-hcd/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,14 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
 BINARY = ehci-hcd
 
Index: uspace/drv/ehci-hcd/hc_iface.c
===================================================================
--- uspace/drv/ehci-hcd/hc_iface.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ehci-hcd/hc_iface.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -106,4 +106,19 @@
 }
 
+/** Find device handle by USB address.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	UNSUPPORTED("find_by_address");
+
+	return ENOTSUP;
+}
+
 /** Release previously requested address.
  *
@@ -321,4 +336,5 @@
 	.request_address = request_address,
 	.bind_address = bind_address,
+	.find_by_address = find_by_address,
 	.release_address = release_address,
 
Index: uspace/drv/ehci-hcd/main.c
===================================================================
--- uspace/drv/ehci-hcd/main.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ehci-hcd/main.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -97,8 +97,12 @@
 	}
 	hc_fun->ops = &hc_ops;
+
 	ret = ddf_fun_bind(hc_fun);
-
 	CHECK_RET_RETURN(ret,
 	    "Failed to bind EHCI function: %s.\n",
+	    str_error(ret));
+	ret = ddf_fun_add_to_class(hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_RETURN(ret,
+	    "Failed to add EHCI to HC class: %s.\n",
 	    str_error(ret));
 
Index: uspace/drv/ehci-hcd/pci.c
===================================================================
--- uspace/drv/ehci-hcd/pci.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ehci-hcd/pci.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -54,5 +54,6 @@
 
 #define CMD_OFFSET 0x0
-#define CONFIGFLAG_OFFSET 0x40
+#define STS_OFFSET 0x4
+#define CFG_OFFSET 0x40
 
 #define USBCMD_RUN 1
@@ -264,7 +265,7 @@
 	 * It would prevent pre-OS code from interfering. */
 	ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
-	   IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGCTLSTS_OFFSET, 0);
+	   IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGCTLSTS_OFFSET,
+	   0xe0000000);
 	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret);
-	usb_log_debug("Zeroed USBLEGCTLSTS register.\n");
 
 	/* Read again Legacy Support and Control register */
@@ -291,10 +292,12 @@
 	volatile uint32_t *usbcmd =
 	    (uint32_t*)((uint8_t*)registers + operation_offset + CMD_OFFSET);
+	volatile uint32_t *usbsts =
+	    (uint32_t*)((uint8_t*)registers + operation_offset + STS_OFFSET);
 	volatile uint32_t *usbconfigured =
-	    (uint32_t*)((uint8_t*)registers + operation_offset
-	    + CONFIGFLAG_OFFSET);
+	    (uint32_t*)((uint8_t*)registers + operation_offset + CFG_OFFSET);
 	usb_log_debug("USBCMD value: %x.\n", *usbcmd);
 	if (*usbcmd & USBCMD_RUN) {
 		*usbcmd = 0;
+		while (!(*usbsts & (1 << 12))); /*wait until hc is halted */
 		*usbconfigured = 0;
 		usb_log_info("EHCI turned off.\n");
@@ -302,4 +305,6 @@
 		usb_log_info("EHCI was not running.\n");
 	}
+	usb_log_debug("Registers: %x(0x00080000):%x(0x00001000):%x(0x0).\n",
+	    *usbcmd, *usbsts, *usbconfigured);
 
 	async_hangup(parent_phone);
Index: uspace/drv/ohci/Makefile
===================================================================
--- uspace/drv/ohci/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,16 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
 BINARY = ohci
 
Index: uspace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/hc.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -40,5 +40,4 @@
 #include <usb/usb.h>
 #include <usb/ddfiface.h>
-#include <usb/usbdevice.h>
 
 #include "hc.h"
@@ -49,5 +48,4 @@
 static int interrupt_emulator(hc_t *instance);
 static void hc_gain_control(hc_t *instance);
-static void hc_init_hw(hc_t *instance);
 static int hc_init_transfer_lists(hc_t *instance);
 static int hc_init_memory(hc_t *instance);
@@ -92,9 +90,9 @@
 		usb_log_error("Failed add root hub match-id.\n");
 	}
+	ret = ddf_fun_bind(hub_fun);
 	return ret;
 }
 /*----------------------------------------------------------------------------*/
-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_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
 {
 	assert(instance);
@@ -111,4 +109,5 @@
 	    ret, str_error(ret));
 
+	list_initialize(&instance->pending_batches);
 	usb_device_keeper_init(&instance->manager);
 	ret = usb_endpoint_manager_init(&instance->ep_manager,
@@ -117,9 +116,12 @@
 	    str_error(ret));
 
-	hc_gain_control(instance);
 	ret = hc_init_memory(instance);
 	CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",
 	    str_error(ret));
-	hc_init_hw(instance);
+#undef CHECK_RET_RETURN
+
+
+//	hc_init_hw(instance);
+	hc_gain_control(instance);
 	fibril_mutex_initialize(&instance->guard);
 
@@ -132,6 +134,4 @@
 	}
 
-	list_initialize(&instance->pending_batches);
-#undef CHECK_RET_RETURN
 	return EOK;
 }
@@ -287,5 +287,5 @@
 {
 	assert(instance);
-	usb_log_debug("OHCI interrupt: %x.\n", status);
+	usb_log_debug("OHCI(%p) interrupt: %x.\n", instance, status);
 	if ((status & ~I_SF) == 0) /* ignore sof status */
 		return;
@@ -339,6 +339,9 @@
 	    (uint32_t*)((char*)instance->registers + 0x100);
 	usb_log_debug("OHCI legacy register %p: %x.\n",
-		ohci_emulation_reg, *ohci_emulation_reg);
-	*ohci_emulation_reg &= ~0x1;
+	    ohci_emulation_reg, *ohci_emulation_reg);
+	/* Do not change A20 state */
+	*ohci_emulation_reg &= 0x100;
+	usb_log_debug("OHCI legacy register %p: %x.\n",
+	    ohci_emulation_reg, *ohci_emulation_reg);
 
 	/* Interrupt routing enabled => smm driver is active */
@@ -350,4 +353,6 @@
 		}
 		usb_log_info("SMM driver: Ownership taken.\n");
+		instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);
+		async_usleep(50000);
 		return;
 	}
@@ -375,5 +380,5 @@
 }
 /*----------------------------------------------------------------------------*/
-void hc_init_hw(hc_t *instance)
+void hc_start_hw(hc_t *instance)
 {
 	/* OHCI guide page 42 */
@@ -474,4 +479,6 @@
 {
 	assert(instance);
+
+	bzero(&instance->rh, sizeof(instance->rh));
 	/* Init queues */
 	hc_init_transfer_lists(instance);
Index: uspace/drv/ohci/hc.h
===================================================================
--- uspace/drv/ohci/hc.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/hc.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -77,6 +77,7 @@
 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_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
+
+void hc_start_hw(hc_t *instance);
 
 /** Safely dispose host controller internal structures
Index: uspace/drv/ohci/hw_struct/endpoint_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/endpoint_descriptor.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/hw_struct/endpoint_descriptor.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -40,5 +40,5 @@
 #include <usb/host/endpoint.h>
 
-#include "utils/malloc32.h"
+#include "../utils/malloc32.h"
 #include "transfer_descriptor.h"
 
Index: uspace/drv/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -33,6 +33,4 @@
  */
 #include <usb/usb.h>
-#include "utils/malloc32.h"
-
 #include "transfer_descriptor.h"
 
Index: uspace/drv/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -37,5 +37,5 @@
 #include <bool.h>
 #include <stdint.h>
-#include "utils/malloc32.h"
+#include "../utils/malloc32.h"
 
 #include "completion_codes.h"
Index: uspace/drv/ohci/iface.c
===================================================================
--- uspace/drv/ohci/iface.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/iface.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -122,4 +122,24 @@
 	return EOK;
 }
+
+
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	bool found =
+	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
+	return found ? EOK : ENOENT;
+}
+
 /*----------------------------------------------------------------------------*/
 /** Release address interface function
@@ -402,4 +422,5 @@
 	.request_address = request_address,
 	.bind_address = bind_address,
+	.find_by_address = find_by_address,
 	.release_address = release_address,
 
Index: uspace/drv/ohci/main.c
===================================================================
--- uspace/drv/ohci/main.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/main.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -43,5 +43,24 @@
 #define NAME "ohci"
 
-static int ohci_add_device(ddf_dev_t *device);
+/** Initializes a new ddf driver instance of OHCI hcd.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int ohci_add_device(ddf_dev_t *device)
+{
+	usb_log_debug("ohci_add_device() called\n");
+	assert(device);
+
+	int ret = device_setup_ohci(device);
+	if (ret != EOK) {
+		usb_log_error("Failed to initialize OHCI driver: %s.\n",
+		    str_error(ret));
+		return ret;
+	}
+	usb_log_info("Controlling new OHCI device '%s'.\n", device->name);
+
+	return EOK;
+}
 /*----------------------------------------------------------------------------*/
 static driver_ops_t ohci_driver_ops = {
@@ -53,32 +72,4 @@
 	.driver_ops = &ohci_driver_ops
 };
-/*----------------------------------------------------------------------------*/
-/** Initializes a new ddf driver instance of OHCI hcd.
- *
- * @param[in] device DDF instance of the device to initialize.
- * @return Error code.
- */
-int ohci_add_device(ddf_dev_t *device)
-{
-	usb_log_debug("ohci_add_device() called\n");
-	assert(device);
-	ohci_t *ohci = malloc(sizeof(ohci_t));
-	if (ohci == NULL) {
-		usb_log_error("Failed to allocate OHCI driver.\n");
-		return ENOMEM;
-	}
-
-	int ret = ohci_init(ohci, device);
-	if (ret != EOK) {
-		usb_log_error("Failed to initialize OHCI driver: %s.\n",
-		    str_error(ret));
-		return ret;
-	}
-	device->driver_data = ohci;
-
-	usb_log_info("Controlling new OHCI device `%s'.\n", device->name);
-
-	return EOK;
-}
 /*----------------------------------------------------------------------------*/
 /** Initializes global driver structures (NONE).
@@ -93,5 +84,4 @@
 {
 	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-	sleep(5);
 	return ddf_driver_main(&ohci_driver);
 }
Index: uspace/drv/ohci/ohci.c
===================================================================
--- uspace/drv/ohci/ohci.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/ohci.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -44,4 +44,21 @@
 #include "iface.h"
 #include "pci.h"
+#include "hc.h"
+#include "root_hub.h"
+
+typedef struct ohci {
+	ddf_fun_t *hc_fun;
+	ddf_fun_t *rh_fun;
+
+	hc_t hc;
+	rh_t rh;
+} ohci_t;
+
+static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
+{
+	assert(dev);
+	assert(dev->driver_data);
+	return dev->driver_data;
+}
 
 /** IRQ handling callback, identifies device
@@ -53,8 +70,7 @@
 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);
+	hc_t *hc = &dev_to_ohci(dev)->hc;
 	assert(hc);
+	const uint16_t status = IPC_GET_ARG1(*call);
 	hc_interrupt(hc, status);
 }
@@ -70,5 +86,5 @@
 {
 	assert(fun);
-	usb_device_keeper_t *manager = &((ohci_t*)fun->dev->driver_data)->hc.manager;
+	usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager;
 
 	usb_address_t addr = usb_device_keeper_find(manager, handle);
@@ -93,13 +109,14 @@
     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;
+	assert(fun);
+	ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
+	assert(hc_fun);
+
+	if (handle != NULL)
+		*handle = hc_fun->handle;
 	return EOK;
 }
 /*----------------------------------------------------------------------------*/
-/** This iface is generic for both RH and HC. */
+/** Root hub USB interface */
 static usb_iface_t usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle,
@@ -107,8 +124,10 @@
 };
 /*----------------------------------------------------------------------------*/
+/** Standard USB HC options (HC interface) */
 static ddf_dev_ops_t hc_ops = {
 	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
 };
 /*----------------------------------------------------------------------------*/
+/** Standard USB RH options (RH interface) */
 static ddf_dev_ops_t rh_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
@@ -117,6 +136,6 @@
 /** Initialize hc and rh ddf structures and their respective drivers.
  *
+ * @param[in] device DDF instance of the device to use.
  * @param[in] instance OHCI structure to use.
- * @param[in] device DDF instance of the device to use.
  *
  * This function does all the preparatory work for hc and rh drivers:
@@ -126,38 +145,55 @@
  *  - registers interrupt handler
  */
-int ohci_init(ohci_t *instance, ddf_dev_t *device)
-{
-	assert(instance);
-	instance->hc_fun = NULL;
+int device_setup_ohci(ddf_dev_t *device)
+{
+	ohci_t *instance = malloc(sizeof(ohci_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate OHCI driver.\n");
+		return ENOMEM;
+	}
+
+#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+if (ret != EOK) { \
+	if (instance->hc_fun) { \
+		instance->hc_fun->ops = NULL; \
+		instance->hc_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->hc_fun); \
+	} \
+	if (instance->rh_fun) { \
+		instance->rh_fun->ops = NULL; \
+		instance->rh_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->rh_fun); \
+	} \
+	free(instance); \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
+
 	instance->rh_fun = NULL;
-#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;
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci-hc");
+	int ret = instance->hc_fun ? EOK : ENOMEM;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n");
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci-rh");
+	ret = instance->rh_fun ? EOK : ENOMEM;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n");
+	instance->rh_fun->ops = &rh_ops;
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
 	int irq = 0;
 
-	int ret =
-	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
-	CHECK_RET_DEST_FUN_RETURN(ret,
+	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to get memory addresses for %" PRIun ": %s.\n",
 	    device->handle, str_error(ret));
 	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
-	    (void *) 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));
+	    (void *) reg_base, reg_size, irq);
 
 	bool interrupts = false;
 #ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, " \
+	usb_log_warning("Interrupts disabled in OS config, "
 	    "falling back to polling.\n");
 #else
@@ -166,5 +202,5 @@
 		usb_log_warning("Failed to enable interrupts: %s.\n",
 		    str_error(ret));
-		usb_log_info("HW interrupts not available, " \
+		usb_log_info("HW interrupts not available, "
 		    "falling back to polling.\n");
 	} else {
@@ -174,30 +210,12 @@
 #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 OHCI device function: %s.\n",
-	    ret, str_error(ret));
-#undef CHECK_RET_HC_RETURN
+	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci-hcd.\n", ret);
 
 #define CHECK_RET_FINI_RETURN(ret, message...) \
 if (ret != EOK) { \
-	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; \
-}
+	CHECK_RET_DEST_FREE_RETURN(ret, message); \
+} else (void)0
 
 	/* It does no harm if we register this on polling */
@@ -207,18 +225,20 @@
 	    "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;
+	ret = ddf_fun_bind(instance->hc_fun);
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to create root hub function.\n", ret);
-
+	    "Failed(%d) to bind OHCI device function: %s.\n",
+	    ret, str_error(ret));
+
+	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
+
+	device->driver_data = instance;
+
+	hc_start_hw(&instance->hc);
 	hc_register_hub(&instance->hc, instance->rh_fun);
-
-	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 OHCI root hub.\n", ret);
-
 	return EOK;
+
+#undef CHECK_RET_DEST_FUN_RETURN
 #undef CHECK_RET_FINI_RETURN
 }
Index: uspace/drv/ohci/ohci.h
===================================================================
--- uspace/drv/ohci/ohci.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/ohci.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -38,16 +38,5 @@
 #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);
+int device_setup_ohci(ddf_dev_t *device);
 
 #endif
Index: uspace/drv/ohci/pci.c
===================================================================
--- uspace/drv/ohci/pci.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/pci.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -58,5 +58,8 @@
     uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
 {
-	assert(dev != NULL);
+	assert(dev);
+	assert(mem_reg_address);
+	assert(mem_reg_size);
+	assert(irq_no);
 
 	int parent_phone = devman_parent_device_connect(dev->handle,
@@ -136,16 +139,4 @@
 	return enabled ? EOK : EIO;
 }
-/*----------------------------------------------------------------------------*/
-/** Implements BIOS handoff routine as decribed in OHCI spec
- *
- * @param[in] device Device asking for interrupts
- * @return Error code.
- */
-int pci_disable_legacy(ddf_dev_t *device)
-{
-	/* TODO: implement */
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
 /**
  * @}
Index: uspace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/root_hub.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -45,5 +45,5 @@
 
 /**
- *	standart device descriptor for ohci root hub
+ * standart device descriptor for ohci root hub
  */
 static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = {
@@ -69,5 +69,4 @@
  */
 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = {
-	/// \TODO some values are default or guessed
 	.attributes = 1 << 7,
 	.configuration_number = 1,
@@ -87,5 +86,4 @@
 	.endpoint_count = 1,
 	.interface_class = USB_CLASS_HUB,
-	/// \TODO is this correct?
 	.interface_number = 1,
 	.interface_protocol = 0,
@@ -107,27 +105,44 @@
 };
 
+/**
+ * bitmask of hub features that are valid to be cleared
+ */
 static const uint32_t hub_clear_feature_valid_mask =
-	(1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) |
+    (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) |
 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
 
+/**
+ * bitmask of hub features that are cleared by writing 1 (and not 0)
+ */
 static const uint32_t hub_clear_feature_by_writing_one_mask =
-	1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER;
-
+    1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER;
+
+/**
+ * bitmask of hub features that are valid to be set
+ */
 static const uint32_t hub_set_feature_valid_mask =
-	(1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) |
+    (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) |
 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
 
-
+/**
+ * bitmask of hub features that are set by writing 1 and cleared by writing 0
+ */
 static const uint32_t hub_set_feature_direct_mask =
-	(1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
-
+    (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
+
+/**
+ * bitmask of port features that are valid to be set
+ */
 static const uint32_t port_set_feature_valid_mask =
-	(1 << USB_HUB_FEATURE_PORT_ENABLE) |
+    (1 << USB_HUB_FEATURE_PORT_ENABLE) |
 (1 << USB_HUB_FEATURE_PORT_SUSPEND) |
 (1 << USB_HUB_FEATURE_PORT_RESET) |
 (1 << USB_HUB_FEATURE_PORT_POWER);
 
+/**
+ * bitmask of port features that can be cleared
+ */
 static const uint32_t port_clear_feature_valid_mask =
-	(1 << USB_HUB_FEATURE_PORT_CONNECTION) |
+    (1 << USB_HUB_FEATURE_PORT_CONNECTION) |
 (1 << USB_HUB_FEATURE_PORT_SUSPEND) |
 (1 << USB_HUB_FEATURE_PORT_OVER_CURRENT) |
@@ -141,10 +156,13 @@
 //USB_HUB_FEATURE_PORT_LOW_SPEED
 
+/**
+ * bitmask with port status changes
+ */
 static const uint32_t port_status_change_mask =
-(1<< USB_HUB_FEATURE_C_PORT_CONNECTION) |
-(1<< USB_HUB_FEATURE_C_PORT_ENABLE) |
-(1<< USB_HUB_FEATURE_C_PORT_OVER_CURRENT) |
-(1<< USB_HUB_FEATURE_C_PORT_RESET) |
-(1<< USB_HUB_FEATURE_C_PORT_SUSPEND);
+    (1 << USB_HUB_FEATURE_C_PORT_CONNECTION) |
+(1 << USB_HUB_FEATURE_C_PORT_ENABLE) |
+(1 << USB_HUB_FEATURE_C_PORT_OVER_CURRENT) |
+(1 << USB_HUB_FEATURE_C_PORT_RESET) |
+(1 << USB_HUB_FEATURE_C_PORT_SUSPEND);
 
 
@@ -154,42 +172,42 @@
 
 static int process_get_port_status_request(rh_t *instance, uint16_t port,
-	usb_transfer_batch_t * request);
+    usb_transfer_batch_t * request);
 
 static int process_get_hub_status_request(rh_t *instance,
-	usb_transfer_batch_t * request);
+    usb_transfer_batch_t * request);
 
 static int process_get_status_request(rh_t *instance,
-	usb_transfer_batch_t * request);
+    usb_transfer_batch_t * request);
 
 static void create_interrupt_mask_in_instance(rh_t *instance);
 
 static int process_get_descriptor_request(rh_t *instance,
-	usb_transfer_batch_t *request);
+    usb_transfer_batch_t *request);
 
 static int process_get_configuration_request(rh_t *instance,
-	usb_transfer_batch_t *request);
+    usb_transfer_batch_t *request);
 
 static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
 
 static int process_hub_feature_clear_request(rh_t *instance,
-	uint16_t feature);
+    uint16_t feature);
 
 static int process_port_feature_set_request(rh_t *instance,
-	uint16_t feature, uint16_t port);
+    uint16_t feature, uint16_t port);
 
 static int process_port_feature_clear_request(rh_t *instance,
-	uint16_t feature, uint16_t port);
+    uint16_t feature, uint16_t port);
 
 static int process_address_set_request(rh_t *instance,
-	uint16_t address);
+    uint16_t address);
 
 static int process_request_with_output(rh_t *instance,
-	usb_transfer_batch_t *request);
+    usb_transfer_batch_t *request);
 
 static int process_request_with_input(rh_t *instance,
-	usb_transfer_batch_t *request);
+    usb_transfer_batch_t *request);
 
 static int process_request_without_data(rh_t *instance,
-	usb_transfer_batch_t *request);
+    usb_transfer_batch_t *request);
 
 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
@@ -198,6 +216,4 @@
 
 static bool is_zeros(void * buffer, size_t size);
-
-
 
 /** Root hub initialization
@@ -210,5 +226,5 @@
 	    (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
 	int opResult = rh_init_descriptors(instance);
-	if(opResult != EOK){
+	if (opResult != EOK) {
 		return opResult;
 	}
@@ -216,11 +232,12 @@
 	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
 	instance->unfinished_interrupt_transfer = NULL;
-	instance->interrupt_mask_size = (instance->port_count + 8)/8;
+	instance->interrupt_mask_size = (instance->port_count + 8) / 8;
 	instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
-	if(!instance->interrupt_buffer)
+	if (!instance->interrupt_buffer)
 		return ENOMEM;
-	
-
-	usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
+
+	usb_log_info("OHCI root hub with %zu ports initialized.\n",
+	    instance->port_count);
+
 	return EOK;
 }
@@ -245,10 +262,10 @@
 		usb_log_info("Root hub got INTERRUPT packet\n");
 		create_interrupt_mask_in_instance(instance);
-		if(is_zeros(instance->interrupt_buffer,
-		    instance->interrupt_mask_size)){
+		if (is_zeros(instance->interrupt_buffer,
+		    instance->interrupt_mask_size)) {
 			usb_log_debug("no changes..\n");
 			instance->unfinished_interrupt_transfer = request;
 			//will be finished later
-		}else{
+		} else {
 			usb_log_debug("processing changes..\n");
 			process_interrupt_mask_in_instance(instance, request);
@@ -256,4 +273,5 @@
 		opResult = EOK;
 	} else {
+
 		opResult = EINVAL;
 		usb_transfer_batch_finish_error(request, opResult);
@@ -271,5 +289,5 @@
  */
 void rh_interrupt(rh_t *instance) {
-	if(!instance->unfinished_interrupt_transfer){
+	if (!instance->unfinished_interrupt_transfer) {
 		return;
 	}
@@ -292,8 +310,8 @@
 static int create_serialized_hub_descriptor(rh_t *instance) {
 	size_t size = 7 +
-	    ((instance->port_count +7 )/ 8) * 2;
-	size_t var_size = (instance->port_count +7 )/ 8;
+	    ((instance->port_count + 7) / 8) * 2;
+	size_t var_size = (instance->port_count + 7) / 8;
 	uint8_t * result = (uint8_t*) malloc(size);
-	if(!result) return ENOMEM;
+	if (!result) return ENOMEM;
 
 	bzero(result, size);
@@ -305,19 +323,19 @@
 	uint32_t hub_desc_reg = instance->registers->rh_desc_a;
 	result[3] =
-		((hub_desc_reg >> 8) % 2) +
-		(((hub_desc_reg >> 9) % 2) << 1) +
-		(((hub_desc_reg >> 10) % 2) << 2) +
-		(((hub_desc_reg >> 11) % 2) << 3) +
-		(((hub_desc_reg >> 12) % 2) << 4);
+	    ((hub_desc_reg >> 8) % 2) +
+	    (((hub_desc_reg >> 9) % 2) << 1) +
+	    (((hub_desc_reg >> 10) % 2) << 2) +
+	    (((hub_desc_reg >> 11) % 2) << 3) +
+	    (((hub_desc_reg >> 12) % 2) << 4);
 	result[4] = 0;
 	result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
 	result[6] = 50;
 
-	int port;
+	size_t port;
 	for (port = 1; port <= instance->port_count; ++port) {
 		uint8_t is_non_removable =
-			instance->registers->rh_desc_b >> port % 2;
+		    instance->registers->rh_desc_b >> port % 2;
 		result[7 + port / 8] +=
-			is_non_removable << (port % 8);
+		    is_non_removable << (port % 8);
 	}
 	size_t i;
@@ -327,4 +345,5 @@
 	instance->hub_descriptor = result;
 	instance->descriptor_size = size;
+
 	return EOK;
 }
@@ -340,38 +359,39 @@
 static int rh_init_descriptors(rh_t *instance) {
 	memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
-		sizeof (ohci_rh_device_descriptor)
-		);
+	    sizeof (ohci_rh_device_descriptor)
+	    );
 	usb_standard_configuration_descriptor_t descriptor;
 	memcpy(&descriptor, &ohci_rh_conf_descriptor,
-		sizeof (ohci_rh_conf_descriptor));
+	    sizeof (ohci_rh_conf_descriptor));
 
 	int opResult = create_serialized_hub_descriptor(instance);
-	if(opResult != EOK){
+	if (opResult != EOK) {
 		return opResult;
 	}
 	descriptor.total_length =
-		sizeof (usb_standard_configuration_descriptor_t) +
-		sizeof (usb_standard_endpoint_descriptor_t) +
-		sizeof (usb_standard_interface_descriptor_t) +
-		instance->descriptor_size;
+	    sizeof (usb_standard_configuration_descriptor_t) +
+	    sizeof (usb_standard_endpoint_descriptor_t) +
+	    sizeof (usb_standard_interface_descriptor_t) +
+	    instance->descriptor_size;
 
 	uint8_t * full_config_descriptor =
-		(uint8_t*) malloc(descriptor.total_length);
-	if(!full_config_descriptor){
+	    (uint8_t*) malloc(descriptor.total_length);
+	if (!full_config_descriptor) {
 		return ENOMEM;
 	}
 	memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
 	memcpy(full_config_descriptor + sizeof (descriptor),
-		&ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
+	    &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
 	memcpy(full_config_descriptor + sizeof (descriptor) +
-		sizeof (ohci_rh_iface_descriptor),
-		&ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
+	    sizeof (ohci_rh_iface_descriptor),
+	    &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
 	memcpy(full_config_descriptor + sizeof (descriptor) +
-		sizeof (ohci_rh_iface_descriptor) +
-		sizeof (ohci_rh_ep_descriptor),
-		instance->hub_descriptor, instance->descriptor_size);
-	
+	    sizeof (ohci_rh_iface_descriptor) +
+	    sizeof (ohci_rh_ep_descriptor),
+	    instance->hub_descriptor, instance->descriptor_size);
+
 	instance->descriptors.configuration = full_config_descriptor;
 	instance->descriptors.configuration_size = descriptor.total_length;
+
 	return EOK;
 }
@@ -389,5 +409,5 @@
  */
 static int process_get_port_status_request(rh_t *instance, uint16_t port,
-	usb_transfer_batch_t * request) {
+    usb_transfer_batch_t * request) {
 	if (port < 1 || port > instance->port_count)
 		return EINVAL;
@@ -398,7 +418,8 @@
 	int i;
 	for (i = 0; i < instance->port_count; ++i) {
+
 		usb_log_debug("port status %d,x%x\n",
-			instance->registers->rh_port_status[i],
-			instance->registers->rh_port_status[i]);
+		    instance->registers->rh_port_status[i],
+		    instance->registers->rh_port_status[i]);
 	}
 #endif
@@ -417,5 +438,5 @@
  */
 static int process_get_hub_status_request(rh_t *instance,
-	usb_transfer_batch_t * request) {
+    usb_transfer_batch_t * request) {
 	uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
 	request->transfered_size = 4;
@@ -423,4 +444,5 @@
 	uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
 	uint32_buffer[0] = mask & instance->registers->rh_status;
+
 	return EOK;
 }
@@ -437,9 +459,9 @@
  */
 static int process_get_status_request(rh_t *instance,
-	usb_transfer_batch_t * request) {
+    usb_transfer_batch_t * request) {
 	size_t buffer_size = request->buffer_size;
 	usb_device_request_setup_packet_t * request_packet =
-		(usb_device_request_setup_packet_t*)
-		request->setup_buffer;
+	    (usb_device_request_setup_packet_t*)
+	    request->setup_buffer;
 
 	usb_hub_bm_request_type_t request_type = request_packet->request_type;
@@ -453,6 +475,7 @@
 	if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
 		return process_get_port_status_request(instance,
-		request_packet->index,
-		request);
+	    request_packet->index,
+	    request);
+
 	return ENOTSUP;
 }
@@ -472,13 +495,14 @@
 	uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
 	uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
-		| (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
+	    | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
 	bzero(bitmap, instance->interrupt_mask_size);
 	if (instance->registers->rh_status & mask) {
 		bitmap[0] = 1;
 	}
-	int port;
+	size_t port;
 	mask = port_status_change_mask;
 	for (port = 1; port <= instance->port_count; ++port) {
 		if (mask & instance->registers->rh_port_status[port - 1]) {
+
 			bitmap[(port) / 8] += 1 << (port % 8);
 		}
@@ -497,7 +521,7 @@
  */
 static int process_get_descriptor_request(rh_t *instance,
-	usb_transfer_batch_t *request) {
+    usb_transfer_batch_t *request) {
 	usb_device_request_setup_packet_t * setup_request =
-		(usb_device_request_setup_packet_t*) request->setup_buffer;
+	    (usb_device_request_setup_packet_t*) request->setup_buffer;
 	size_t size;
 	const void * result_descriptor = NULL;
@@ -543,13 +567,13 @@
 		{
 			usb_log_debug("USB_DESCTYPE_EINVAL %d \n",
-				setup_request->value);
+			    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
-				);
+			    "%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;
 		}
@@ -560,4 +584,5 @@
 	request->transfered_size = size;
 	memcpy(request->data_buffer, result_descriptor, size);
+
 	return EOK;
 }
@@ -573,5 +598,5 @@
  */
 static int process_get_configuration_request(rh_t *instance,
-	usb_transfer_batch_t *request) {
+    usb_transfer_batch_t *request) {
 	//set and get configuration requests do not have any meaning, only dummy
 	//values are returned
@@ -580,4 +605,5 @@
 	request->data_buffer[0] = 1;
 	request->transfered_size = 1;
+
 	return EOK;
 }
@@ -592,12 +618,13 @@
  */
 static int process_hub_feature_set_request(rh_t *instance,
-	uint16_t feature) {
+    uint16_t feature) {
 	if (!((1 << feature) & hub_set_feature_valid_mask))
 		return EINVAL;
-	if(feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
+	if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
 		feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
 	instance->registers->rh_status =
-		(instance->registers->rh_status | (1 << feature))
-		& (~hub_clear_feature_by_writing_one_mask);
+	    (instance->registers->rh_status | (1 << feature))
+	    & (~hub_clear_feature_by_writing_one_mask);
+
 	return EOK;
 }
@@ -612,5 +639,5 @@
  */
 static int process_hub_feature_clear_request(rh_t *instance,
-	uint16_t feature) {
+    uint16_t feature) {
 	if (!((1 << feature) & hub_clear_feature_valid_mask))
 		return EINVAL;
@@ -618,11 +645,12 @@
 	if ((1 << feature) & hub_set_feature_direct_mask) {
 		instance->registers->rh_status =
-			(instance->registers->rh_status & (~(1 << feature)))
-			& (~hub_clear_feature_by_writing_one_mask);
+		    (instance->registers->rh_status & (~(1 << feature)))
+		    & (~hub_clear_feature_by_writing_one_mask);
 	} else {//the feature is cleared by writing '1'
+
 		instance->registers->rh_status =
-			(instance->registers->rh_status
-			& (~hub_clear_feature_by_writing_one_mask))
-			| (1 << feature);
+		    (instance->registers->rh_status
+		    & (~hub_clear_feature_by_writing_one_mask))
+		    | (1 << feature);
 	}
 	return EOK;
@@ -640,5 +668,5 @@
  */
 static int process_port_feature_set_request(rh_t *instance,
-	uint16_t feature, uint16_t port) {
+    uint16_t feature, uint16_t port) {
 	if (!((1 << feature) & port_set_feature_valid_mask))
 		return EINVAL;
@@ -646,7 +674,8 @@
 		return EINVAL;
 	instance->registers->rh_port_status[port - 1] =
-		(instance->registers->rh_port_status[port - 1] | (1 << feature))
-		& (~port_clear_feature_valid_mask);
+	    (instance->registers->rh_port_status[port - 1] | (1 << feature))
+	    & (~port_clear_feature_valid_mask);
 	/// \TODO any error?
+
 	return EOK;
 }
@@ -663,5 +692,5 @@
  */
 static int process_port_feature_clear_request(rh_t *instance,
-	uint16_t feature, uint16_t port) {
+    uint16_t feature, uint16_t port) {
 	if (!((1 << feature) & port_clear_feature_valid_mask))
 		return EINVAL;
@@ -673,8 +702,9 @@
 		feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
 	instance->registers->rh_port_status[port - 1] =
-		(instance->registers->rh_port_status[port - 1]
-		& (~port_clear_feature_valid_mask))
-		| (1 << feature);
+	    (instance->registers->rh_port_status[port - 1]
+	    & (~port_clear_feature_valid_mask))
+	    | (1 << feature);
 	/// \TODO any error?
+
 	return EOK;
 }
@@ -689,6 +719,7 @@
  */
 static int process_address_set_request(rh_t *instance,
-	uint16_t address) {
+    uint16_t address) {
 	instance->address = address;
+
 	return EOK;
 }
@@ -705,7 +736,7 @@
  */
 static int process_request_with_output(rh_t *instance,
-	usb_transfer_batch_t *request) {
+    usb_transfer_batch_t *request) {
 	usb_device_request_setup_packet_t * setup_request =
-		(usb_device_request_setup_packet_t*) request->setup_buffer;
+	    (usb_device_request_setup_packet_t*) request->setup_buffer;
 	if (setup_request->request == USB_DEVREQ_GET_STATUS) {
 		usb_log_debug("USB_DEVREQ_GET_STATUS\n");
@@ -718,4 +749,5 @@
 	if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
 		usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
+
 		return process_get_configuration_request(instance, request);
 	}
@@ -734,7 +766,7 @@
  */
 static int process_request_with_input(rh_t *instance,
-	usb_transfer_batch_t *request) {
+    usb_transfer_batch_t *request) {
 	usb_device_request_setup_packet_t * setup_request =
-		(usb_device_request_setup_packet_t*) request->setup_buffer;
+	    (usb_device_request_setup_packet_t*) request->setup_buffer;
 	request->transfered_size = 0;
 	if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
@@ -744,4 +776,5 @@
 		//set and get configuration requests do not have any meaning,
 		//only dummy values are returned
+
 		return EOK;
 	}
@@ -760,7 +793,7 @@
  */
 static int process_request_without_data(rh_t *instance,
-	usb_transfer_batch_t *request) {
+    usb_transfer_batch_t *request) {
 	usb_device_request_setup_packet_t * setup_request =
-		(usb_device_request_setup_packet_t*) request->setup_buffer;
+	    (usb_device_request_setup_packet_t*) request->setup_buffer;
 	request->transfered_size = 0;
 	if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
@@ -768,14 +801,14 @@
 			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
 			return process_hub_feature_clear_request(instance,
-				setup_request->value);
+			    setup_request->value);
 		}
 		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
 			usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
 			return process_port_feature_clear_request(instance,
-				setup_request->value,
-				setup_request->index);
+			    setup_request->value,
+			    setup_request->index);
 		}
 		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
-			setup_request->request_type);
+		    setup_request->request_type);
 		return EINVAL;
 	}
@@ -784,14 +817,14 @@
 			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
 			return process_hub_feature_set_request(instance,
-				setup_request->value);
+			    setup_request->value);
 		}
 		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
 			usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
 			return process_port_feature_set_request(instance,
-				setup_request->value,
-				setup_request->index);
+			    setup_request->value,
+			    setup_request->index);
 		}
 		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
-			setup_request->request_type);
+		    setup_request->request_type);
 		return EINVAL;
 	}
@@ -799,8 +832,9 @@
 		usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
 		return process_address_set_request(instance,
-			setup_request->value);
+		    setup_request->value);
 	}
 	usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
-		setup_request->request_type);
+	    setup_request->request_type);
+
 	return ENOTSUP;
 }
@@ -836,9 +870,9 @@
 	}
 	usb_log_info("CTRL packet: %s.\n",
-		usb_debug_str_buffer(
-		(const uint8_t *) request->setup_buffer, 8, 8));
+	    usb_debug_str_buffer(
+	    (const uint8_t *) request->setup_buffer, 8, 8));
 	usb_device_request_setup_packet_t * setup_request =
-		(usb_device_request_setup_packet_t*)
-		request->setup_buffer;
+	    (usb_device_request_setup_packet_t*)
+	    request->setup_buffer;
 	switch (setup_request->request) {
 		case USB_DEVREQ_GET_STATUS:
@@ -847,5 +881,5 @@
 			usb_log_debug("processing request with output\n");
 			opResult = process_request_with_output(
-				instance, request);
+			    instance, request);
 			break;
 		case USB_DEVREQ_CLEAR_FEATURE:
@@ -853,20 +887,21 @@
 		case USB_DEVREQ_SET_ADDRESS:
 			usb_log_debug("processing request without "
-				"additional data\n");
+			    "additional data\n");
 			opResult = process_request_without_data(
-				instance, request);
+			    instance, request);
 			break;
 		case USB_DEVREQ_SET_DESCRIPTOR:
 		case USB_DEVREQ_SET_CONFIGURATION:
 			usb_log_debug("processing request with "
-				"input\n");
+			    "input\n");
 			opResult = process_request_with_input(
-				instance, request);
+			    instance, request);
+
 			break;
 		default:
 			usb_log_warning("received unsuported request: "
-				"%d\n",
-				setup_request->request
-				);
+			    "%d\n",
+			    setup_request->request
+			    );
 			opResult = ENOTSUP;
 	}
@@ -888,5 +923,5 @@
  * @return
  */
-static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){
+static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request) {
 	memcpy(request->data_buffer, instance->interrupt_buffer,
 	    instance->interrupt_mask_size);
@@ -894,4 +929,5 @@
 	instance->unfinished_interrupt_transfer = NULL;
 	usb_transfer_batch_finish_error(request, EOK);
+
 	return EOK;
 }
@@ -907,10 +943,10 @@
  * @return
  */
-static bool is_zeros(void * buffer, size_t size){
-	if(!buffer) return true;
-	if(!size) return true;
+static bool is_zeros(void * buffer, size_t size) {
+	if (!buffer) return true;
+	if (!size) return true;
 	size_t i;
-	for(i=0;i<size;++i){
-		if(((char*)buffer)[i])
+	for (i = 0; i < size; ++i) {
+		if (((char*) buffer)[i])
 			return false;
 	}
Index: uspace/drv/ohci/root_hub.h
===================================================================
--- uspace/drv/ohci/root_hub.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/ohci/root_hub.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -51,5 +51,5 @@
 	usb_address_t address;
 	/** hub port count */
-	int port_count;
+	size_t port_count;
 	/** hubs descriptors */
 	usb_device_descriptors_t descriptors;
Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,14 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
 BINARY = uhci-hcd
 
Index: uspace/drv/uhci-hcd/hc.c
===================================================================
--- uspace/drv/uhci-hcd/hc.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/hc.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -60,5 +60,4 @@
  *
  * @param[in] instance Memory place to initialize.
- * @param[in] fun DDF function.
  * @param[in] regs Address of I/O control registers.
  * @param[in] size Size of I/O control registers.
@@ -69,6 +68,5 @@
  * interrupt fibrils.
  */
-int hc_init(hc_t *instance, ddf_fun_t *fun,
-    void *regs, size_t reg_size, bool interrupts)
+int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
 {
 	assert(reg_size >= sizeof(regs_t));
Index: uspace/drv/uhci-hcd/hc.h
===================================================================
--- uspace/drv/uhci-hcd/hc.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/hc.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -136,6 +136,5 @@
 } hc_t;
 
-int hc_init(hc_t *instance, ddf_fun_t *fun,
-    void *regs, size_t reg_size, bool interupts);
+int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
 
 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
Index: uspace/drv/uhci-hcd/hw_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/queue_head.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/hw_struct/queue_head.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -38,5 +38,5 @@
 #include "link_pointer.h"
 #include "transfer_descriptor.h"
-#include "utils/malloc32.h"
+#include "../utils/malloc32.h"
 
 /** This structure is defined in UHCI design guide p. 31 */
Index: uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -36,5 +36,5 @@
 
 #include "transfer_descriptor.h"
-#include "utils/malloc32.h"
+#include "../utils/malloc32.h"
 
 /** Initialize Transfer Descriptor
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/iface.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -122,4 +122,23 @@
 	return EOK;
 }
+
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	bool found =
+	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
+	return found ? EOK : ENOENT;
+}
+
 /*----------------------------------------------------------------------------*/
 /** Release address interface function
@@ -352,4 +371,5 @@
 	.request_address = request_address,
 	.bind_address = bind_address,
+	.find_by_address = find_by_address,
 	.release_address = release_address,
 
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/main.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -64,11 +64,5 @@
 	assert(device);
 
-	uhci_t *uhci = malloc(sizeof(uhci_t));
-	if (uhci == NULL) {
-		usb_log_error("Failed to allocate UHCI driver.\n");
-		return ENOMEM;
-	}
-
-	int ret = uhci_init(uhci, device);
+	int ret = device_setup_uhci(device);
 	if (ret != EOK) {
 		usb_log_error("Failed to initialize UHCI driver: %s.\n",
@@ -76,6 +70,4 @@
 		return ret;
 	}
-	device->driver_data = uhci;
-
 	usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
 
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -44,4 +44,28 @@
 #include "pci.h"
 
+#include "hc.h"
+#include "root_hub.h"
+
+/** Structure representing both functions of UHCI hc, USB host controller
+ * and USB root hub */
+typedef struct uhci {
+	/** Pointer to DDF represenation of UHCI host controller */
+	ddf_fun_t *hc_fun;
+	/** Pointer to DDF represenation of UHCI root hub */
+	ddf_fun_t *rh_fun;
+
+	/** Internal driver's represenation of UHCI host controller */
+	hc_t hc;
+	/** Internal driver's represenation of UHCI root hub */
+	rh_t rh;
+} uhci_t;
+
+static inline uhci_t * dev_to_uhci(ddf_dev_t *dev)
+{
+	assert(dev);
+	assert(dev->driver_data);
+	return dev->driver_data;
+}
+/*----------------------------------------------------------------------------*/
 /** IRQ handling callback, forward status from call to diver structure.
  *
@@ -69,8 +93,7 @@
 {
 	assert(fun);
-	usb_device_keeper_t *manager =
-	    &((uhci_t*)fun->dev->driver_data)->hc.manager;
-
+	usb_device_keeper_t *manager = &dev_to_uhci(fun->dev)->hc.manager;
 	usb_address_t addr = usb_device_keeper_find(manager, handle);
+
 	if (addr < 0) {
 		return addr;
@@ -93,9 +116,10 @@
     ddf_fun_t *fun, devman_handle_t *handle)
 {
-	assert(handle);
-	ddf_fun_t *hc_fun = ((uhci_t*)fun->dev->driver_data)->hc_fun;
-	assert(hc_fun != NULL);
-
-	*handle = hc_fun->handle;
+	assert(fun);
+	ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun;
+	assert(hc_fun);
+
+	if (handle != NULL)
+		*handle = hc_fun->handle;
 	return EOK;
 }
@@ -126,5 +150,5 @@
 static hw_res_ops_t hw_res_iface = {
 	.get_resource_list = get_resource_list,
-	.enable_interrupt = NULL
+	.enable_interrupt = NULL,
 };
 /*----------------------------------------------------------------------------*/
@@ -146,33 +170,55 @@
  *  - registers interrupt handler
  */
-int uhci_init(uhci_t *instance, ddf_dev_t *device)
-{
-	assert(instance);
-	instance->hc_fun = NULL;
+int device_setup_uhci(ddf_dev_t *device)
+{
+	assert(device);
+	uhci_t *instance = malloc(sizeof(uhci_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate OHCI driver.\n");
+		return ENOMEM;
+	}
+
+#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+if (ret != EOK) { \
+	if (instance->hc_fun) \
+		instance->hc_fun->ops = NULL; \
+		instance->hc_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) {\
+		instance->rh_fun->ops = NULL; \
+		instance->rh_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->rh_fun); \
+	} \
+	free(instance); \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
+
 	instance->rh_fun = NULL;
-#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 io_reg_base = 0;
-	size_t io_reg_size = 0;
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc");
+	int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
+	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
+	instance->rh_fun->ops = &rh_ops;
+	instance->rh_fun->driver_data = &instance->rh;
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
 	int irq = 0;
 
-	int ret =
-	    pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
-	CHECK_RET_DEST_FUN_RETURN(ret,
+	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed to get I/O addresses for %" PRIun ": %s.\n",
 	    device->handle, str_error(ret));
 	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
-	    (void *) io_reg_base, io_reg_size, irq);
+	    (void *) reg_base, reg_size, irq);
 
 	ret = pci_disable_legacy(device);
-	CHECK_RET_DEST_FUN_RETURN(ret,
+	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
 
@@ -194,32 +240,15 @@
 #endif
 
-	instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc");
-	ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
-	CHECK_RET_DEST_FUN_RETURN(ret,
-	    "Failed(%d) to create HC function: %s.\n", ret, str_error(ret));
-
-	ret = hc_init(&instance->hc, instance->hc_fun,
-	    (void*)io_reg_base, io_reg_size, interrupts);
-	CHECK_RET_DEST_FUN_RETURN(ret,
+
+	ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
+	CHECK_RET_DEST_FREE_RETURN(ret,
 	    "Failed(%d) to init uhci-hcd: %s.\n", ret, str_error(ret));
-
-	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); \
+	CHECK_RET_DEST_FREE_RETURN(ret, message); \
 	return ret; \
-}
+} else (void)0
 
 	/* It does no harm if we register this on polling */
@@ -230,9 +259,12 @@
 	    ret, str_error(ret));
 
-	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
-	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to create root hub function: %s.\n",
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed(%d) to bind UHCI device function: %s.\n",
 	    ret, str_error(ret));
+
+	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to add UHCI to HC class: %s.\n", str_error(ret));
 
 	ret = rh_init(&instance->rh, instance->rh_fun,
@@ -241,10 +273,9 @@
 	    "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
 
-	instance->rh_fun->ops = &rh_ops;
-	instance->rh_fun->driver_data = &instance->rh;
 	ret = ddf_fun_bind(instance->rh_fun);
 	CHECK_RET_FINI_RETURN(ret,
 	    "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
 
+	device->driver_data = instance;
 	return EOK;
 #undef CHECK_RET_FINI_RETURN
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -38,22 +38,5 @@
 #include <ddf/driver.h>
 
-#include "hc.h"
-#include "root_hub.h"
-
-/** Structure representing both functions of UHCI hc, USB host controller
- * and USB root hub */
-typedef struct uhci {
-	/** Pointer to DDF represenation of UHCI host controller */
-	ddf_fun_t *hc_fun;
-	/** Pointer to DDF represenation of UHCI root hub */
-	ddf_fun_t *rh_fun;
-
-	/** Internal driver's represenation of UHCI host controller */
-	hc_t hc;
-	/** Internal driver's represenation of UHCI root hub */
-	rh_t rh;
-} uhci_t;
-
-int uhci_init(uhci_t *instance, ddf_dev_t *device);
+int device_setup_uhci(ddf_dev_t *device);
 #endif
 /**
Index: uspace/drv/uhci-rhd/Makefile
===================================================================
--- uspace/drv/uhci-rhd/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-rhd/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,14 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
 BINARY = uhci-rhd
 
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/uhci-rhd/port.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -32,11 +32,11 @@
  * @brief UHCI root hub port routines
  */
-#include <libarch/ddi.h> /* pio_read and pio_write */
+#include <libarch/ddi.h>  /* pio_read and pio_write */
+#include <fibril_synch.h> /* async_usleep */
 #include <errno.h>
 #include <str_error.h>
-#include <fibril_synch.h>
 
 #include <usb/usb.h>    /* usb_address_t */
-#include <usb/hub.h>
+#include <usb/hub.h>    /* usb_hc_new_device_wrapper */
 #include <usb/debug.h>
 
@@ -212,11 +212,5 @@
 
 	/*
-	 * The host then waits for at least 100 ms to allow completion of
-	 * an insertion process and for power at the device to become stable.
-	 */
-	async_usleep(100000);
-
-	/*
-	 * Resets from root ports should be nominally 50ms
+	 * Resets from root ports should be nominally 50ms (USB spec 7.1.7.3)
 	 */
 	{
@@ -229,12 +223,17 @@
 		port_status &= ~STATUS_IN_RESET;
 		uhci_port_write_status(port, port_status);
-		usb_log_debug("%s: Reset Signal stop.\n", port->id_string);
-	}
-
-	/* the reset recovery time 10ms */
-	async_usleep(10000);
-
+		while (uhci_port_read_status(port) & STATUS_IN_RESET);
+		// TODO: find a better way to waste time (it should be less than
+		// 10ms, if we reschedule it takes too much time (random
+		// interrupts can be solved by multiple attempts).
+		usb_log_debug2("%s: Reset Signal stop.\n", port->id_string);
+	}
 	/* Enable the port. */
 	uhci_port_set_enabled(port, true);
+
+	/* Reset recovery period,
+	 * devices do not have to respond during this period
+	 */
+	async_usleep(10000);
 	return EOK;
 }
@@ -255,8 +254,11 @@
 	usb_log_debug("%s: Detected new device.\n", port->id_string);
 
+	int ret, count = 0;
 	usb_address_t dev_addr;
-	int ret = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
-	    speed, uhci_port_reset_enable, port->number, port,
-	    &dev_addr, &port->attached_device, NULL, NULL, NULL);
+	do {
+		ret = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
+		    speed, uhci_port_reset_enable, port->number, port,
+		    &dev_addr, &port->attached_device, NULL, NULL, NULL);
+	} while (ret != EOK && ++count < 4);
 
 	if (ret != EOK) {
@@ -313,5 +315,4 @@
 	/* Wait for port to become enabled */
 	do {
-		async_usleep(1000);
 		port_status = uhci_port_read_status(port);
 	} while ((port_status & STATUS_CONNECTED) &&
Index: uspace/drv/usbflbk/Makefile
===================================================================
--- uspace/drv/usbflbk/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbflbk/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,14 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
 BINARY = usbflbk
 
Index: uspace/drv/usbhid/Makefile
===================================================================
--- uspace/drv/usbhid/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbhid/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,17 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+
+LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I. \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
 BINARY = usbhid
 
Index: uspace/drv/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbhid/mouse/mousedev.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -309,5 +309,5 @@
 	 * Wheel
 	 */
-	int wheel;
+	int wheel = 0;
 	
 	path = usb_hid_report_path();
Index: uspace/drv/usbhub/Makefile
===================================================================
--- uspace/drv/usbhub/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbhub/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,14 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
 BINARY = usbhub
 
Index: uspace/drv/usbhub/ports.c
===================================================================
--- uspace/drv/usbhub/ports.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbhub/ports.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -53,4 +53,19 @@
 	size_t port;
 	usb_speed_t speed;
+};
+
+/**
+ * count of port status changes that are not explicitly handled by
+ * any function here and must be cleared by hand
+ */
+static const unsigned int non_handled_changes_count = 2;
+
+/**
+ * port status changes that are not explicitly handled by
+ * any function here and must be cleared by hand
+ */
+static const int non_handled_changes[] =  {
+	USB_HUB_FEATURE_C_PORT_ENABLE,
+	USB_HUB_FEATURE_C_PORT_SUSPEND
 };
 
@@ -131,14 +146,34 @@
 	    &status, USB_HUB_FEATURE_C_PORT_CONNECTION,false);
 	usb_port_status_set_bit(
-	    &status, USB_HUB_FEATURE_PORT_RESET,false);
-	usb_port_status_set_bit(
 	    &status, USB_HUB_FEATURE_C_PORT_RESET,false);
 	usb_port_status_set_bit(
 	    &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT,false);
-	/// \TODO what about port power change?
-	if (status >> 16) {
-		usb_log_info("there was unsupported change on port %d: %X\n",
-			port, status);
-
+	
+	//clearing not yet handled changes	
+	unsigned int feature_idx;
+	for(feature_idx = 0;feature_idx<non_handled_changes_count;
+	    ++feature_idx){
+		unsigned int bit_idx = non_handled_changes[feature_idx];
+		if(status & (1<<bit_idx)){
+			usb_log_info(
+			    "there was not yet handled change on port %d: %d"
+			    ";clearing it\n",
+			port, bit_idx);
+			int opResult = usb_hub_clear_port_feature(
+			    hub->control_pipe,
+			    port, bit_idx);
+			if (opResult != EOK) {
+				usb_log_warning(
+				    "could not clear port flag %d: %d\n",
+				    bit_idx, opResult
+				    );
+			}
+			usb_port_status_set_bit(
+			    &status, bit_idx,false);
+		}
+	}
+	if(status>>16){
+		usb_log_info("there is still some unhandled change %X\n",
+		    status);
 	}
 }
@@ -222,4 +257,11 @@
 		    "Port %zu reset complete but port not enabled.\n",
 		    (size_t) port);
+	}
+	/* Clear the port reset change. */
+	int rc = usb_hub_clear_port_feature(hub->control_pipe,
+	    port, USB_HUB_FEATURE_C_PORT_RESET);
+	if (rc != EOK) {
+		usb_log_error("Failed to clear port %d reset feature: %s.\n",
+		    port, str_error(rc));
 	}
 }
@@ -319,13 +361,4 @@
 	fibril_mutex_unlock(&my_port->reset_mutex);
 
-	/* Clear the port reset change. */
-	rc = usb_hub_clear_port_feature(hub->control_pipe,
-	    port_no, USB_HUB_FEATURE_C_PORT_RESET);
-	if (rc != EOK) {
-		usb_log_error("Failed to clear port %d reset feature: %s.\n",
-		    port_no, str_error(rc));
-		return rc;
-	}
-
 	if (my_port->reset_okay) {
 		return EOK;
Index: uspace/drv/usbmast/Makefile
===================================================================
--- uspace/drv/usbmast/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbmast/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,9 +28,18 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
 BINARY = usbmast
 
 SOURCES = \
+	inquiry.c \
 	main.c \
 	mast.c
Index: uspace/drv/usbmast/inquiry.c
===================================================================
--- uspace/drv/usbmast/inquiry.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
+++ uspace/drv/usbmast/inquiry.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbmast
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB mass storage driver.
+ */
+#include <usb/devdrv.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/massstor.h>
+#include <errno.h>
+#include <str_error.h>
+#include <str.h>
+#include <ctype.h>
+#include "cmds.h"
+#include "scsi.h"
+#include "mast.h"
+
+#define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
+#define BITS_GET_MID_MASK(type, bitcount, offset) \
+	((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
+#define BITS_GET(type, number, bitcount, offset) \
+	((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
+
+#define INQUIRY_RESPONSE_LENGTH 36
+
+#define STR_UNKNOWN "<unknown>"
+
+/** String constants for SCSI peripheral device types. */
+static const char *str_peripheral_device_types[] = {
+	"direct-access device",
+	"sequential-access device",
+	"printer device",
+	"processor device",
+	"write-once device",
+	"CDROM device",
+	"scanner device",
+	"optical memory device",
+	"medium changer",
+	"communications device",
+	"graphic arts pre-press device",
+	"graphic arts pre-press device",
+	"storage array controller device",
+	"enclosure services device",
+	"simplified direct-access device",
+	"optical card reader/writer device",
+	"bridging expander",
+	"object-based storage device",
+	"automation driver interface",
+	STR_UNKNOWN, // 0x13
+	STR_UNKNOWN, // 0x14
+	STR_UNKNOWN, // 0x15
+	STR_UNKNOWN, // 0x16
+	STR_UNKNOWN, // 0x17
+	STR_UNKNOWN, // 0x18
+	STR_UNKNOWN, // 0x19
+	STR_UNKNOWN, // 0x1A
+	STR_UNKNOWN, // 0x1B
+	STR_UNKNOWN, // 0x1C
+	STR_UNKNOWN, // 0x1D
+	"well-known logical unit",
+	"uknown or no device state"
+};
+#define str_peripheral_device_types_count \
+	(sizeof(str_peripheral_device_types)/sizeof(str_peripheral_device_types[0]))
+
+/** Get string representation for SCSI peripheral device type.
+ *
+ * See for example here for a list
+ * http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type.
+ *
+ * @param type SCSI peripheral device type code.
+ * @return String representation.
+ */
+const char *usb_str_masstor_scsi_peripheral_device_type(int type)
+{
+	if ((type < 0)
+	    || ((size_t)type >= str_peripheral_device_types_count)) {
+		return STR_UNKNOWN;
+	}
+	return str_peripheral_device_types[type];
+}
+
+/** Trim trailing spaces from a string (rewrite with string terminator).
+ *
+ * @param name String to be trimmed (in-out parameter).
+ */
+static void trim_trailing_spaces(char *name)
+{
+	size_t len = str_length(name);
+	while ((len > 0) && isspace((int) name[len - 1])) {
+		name[len - 1] = 0;
+		len--;
+	}
+}
+
+/** Perform SCSI INQUIRY command on USB mass storage device.
+ *
+ * @param dev USB device.
+ * @param bulk_in_idx Index (in dev->pipes) of bulk in pipe.
+ * @param bulk_out_idx Index of bulk out pipe.
+ * @param inquiry_result Where to store parsed inquiry result.
+ * @return Error code.
+ */
+int usb_massstor_inquiry(usb_device_t *dev,
+    size_t bulk_in_idx, size_t bulk_out_idx,
+    usb_massstor_inquiry_result_t *inquiry_result)
+{
+	scsi_cmd_inquiry_t inquiry = {
+		.op_code = 0x12,
+		.lun_evpd = 0,
+		.page_code = 0,
+		.alloc_length = host2uint16_t_be(INQUIRY_RESPONSE_LENGTH),
+		.ctrl = 0
+	};
+	size_t response_len;
+	uint8_t response[INQUIRY_RESPONSE_LENGTH];
+
+	int rc;
+
+	rc = usb_massstor_data_in(dev, bulk_in_idx, bulk_out_idx,
+	    0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
+	    response, INQUIRY_RESPONSE_LENGTH, &response_len);
+
+	if (rc != EOK) {
+		usb_log_error("Failed to probe device %s using %s: %s.\n",
+		   dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
+		return rc;
+	}
+
+	if (response_len < 8) {
+		usb_log_error("The SCSI response is too short.\n");
+		return ERANGE;
+	}
+
+	/*
+	 * This is an ugly part of the code. We will parse the returned
+	 * data by hand and try to get as many useful data as possible.
+	 */
+	bzero(inquiry_result, sizeof(*inquiry_result));
+
+	/* This shall be returned by all devices. */
+	inquiry_result->peripheral_device_type
+	    = BITS_GET(uint8_t, response[0], 5, 0);
+	inquiry_result->removable = BITS_GET(uint8_t, response[1], 1, 7);
+
+	if (response_len < 32) {
+		return EOK;
+	}
+
+	str_ncpy(inquiry_result->vendor_id, 9,
+	    (const char *) &response[8], 8);
+	trim_trailing_spaces(inquiry_result->vendor_id);
+
+	str_ncpy(inquiry_result->product_and_revision, 12,
+	    (const char *) &response[16], 11);
+	trim_trailing_spaces(inquiry_result->product_and_revision);
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbmast/main.c
===================================================================
--- uspace/drv/usbmast/main.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbmast/main.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -75,65 +75,4 @@
 };
 
-#define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
-#define BITS_GET_MID_MASK(type, bitcount, offset) \
-	((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
-#define BITS_GET(type, number, bitcount, offset) \
-	((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
-
-#define INQUIRY_RESPONSE_LENGTH 35
-
-static void try_inquiry(usb_device_t *dev)
-{
-	scsi_cmd_inquiry_t inquiry = {
-		.op_code = 0x12,
-		.lun_evpd = 0,
-		.page_code = 0,
-		.alloc_length = INQUIRY_RESPONSE_LENGTH,
-		.ctrl = 0
-	};
-	size_t response_len;
-	uint8_t response[INQUIRY_RESPONSE_LENGTH];
-
-	int rc;
-
-	rc = usb_massstor_data_in(GET_BULK_IN(dev), GET_BULK_OUT(dev),
-	    0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
-	    response, INQUIRY_RESPONSE_LENGTH, &response_len);
-
-	if (rc != EOK) {
-		usb_log_error("Failed to probe device %s using %s: %s.\n",
-		   dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
-		return;
-	}
-
-	if (response_len < 8) {
-		usb_log_error("The SCSI response is too short.\n");
-		return;
-	}
-
-	/*
-	 * This is an ugly part of the code. We will parse the returned
-	 * data by hand and try to get as many useful data as possible.
-	 */
-	int device_type = BITS_GET(uint8_t, response[0], 5, 0);
-	int removable = BITS_GET(uint8_t, response[1], 1, 7);
-
-	usb_log_info("SCSI information for device `%s':\n", dev->ddf_dev->name);
-	usb_log_info("  - peripheral device type: %d\n", device_type);
-	usb_log_info("  - removable: %s\n", removable ? "yes" : "no");
-
-	if (response_len < 32) {
-		return;
-	}
-
-	char dev_vendor[9];
-	str_ncpy(dev_vendor, 9, (const char *) &response[8], 8);
-	usb_log_info("  - vendor: '%s'\n", dev_vendor);
-
-	char dev_product[9];
-	str_ncpy(dev_product, 9, (const char *) &response[16], 8);
-	usb_log_info("  - product: '%s'\n", dev_vendor);
-}
-
 /** Callback when new device is attached and recognized as a mass storage.
  *
@@ -168,5 +107,21 @@
 	    (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
 
-	try_inquiry(dev);
+	size_t lun_count = usb_masstor_get_lun_count(dev);
+
+	usb_massstor_inquiry_result_t inquiry;
+	rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry);
+	if (rc != EOK) {
+		usb_log_warning("Failed to inquiry device `%s': %s.\n",
+		    dev->ddf_dev->name, str_error(rc));
+		return EOK;
+	}
+
+	usb_log_info("Mass storage `%s': " \
+	    "`%s' by `%s' is %s (%s), %zu LUN(s).\n",
+	    dev->ddf_dev->name,
+	    inquiry.product_and_revision, inquiry.vendor_id,
+	    usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type),
+	    inquiry.removable ? "removable" : "non-removable",
+	    lun_count);
 
 	return EOK;
Index: uspace/drv/usbmast/mast.c
===================================================================
--- uspace/drv/usbmast/mast.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbmast/mast.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -40,4 +40,5 @@
 #include <str_error.h>
 #include <usb/debug.h>
+#include <usb/request.h>
 
 bool usb_mast_verbose = true;
@@ -63,5 +64,6 @@
  * @return Error code.
  */
-int usb_massstor_data_in(usb_pipe_t *bulk_in_pipe, usb_pipe_t *bulk_out_pipe,
+int usb_massstor_data_in(usb_device_t *dev,
+    size_t bulk_in_pipe_index, size_t bulk_out_pipe_index,
     uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
     void *in_buffer, size_t in_buffer_size, size_t *received_size)
@@ -69,4 +71,6 @@
 	int rc;
 	size_t act_size;
+	usb_pipe_t *bulk_in_pipe = dev->pipes[bulk_in_pipe_index].pipe;
+	usb_pipe_t *bulk_out_pipe = dev->pipes[bulk_out_pipe_index].pipe;
 
 	/* Prepare CBW - command block wrapper */
@@ -135,4 +139,83 @@
 }
 
+/** Perform bulk-only mass storage reset.
+ *
+ * @param dev Device to be reseted.
+ * @return Error code.
+ */
+int usb_massstor_reset(usb_device_t *dev)
+{
+	return usb_control_request_set(&dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
+	    0xFF, 0, dev->interface_no, NULL, 0);
+}
+
+/** Perform complete reset recovery of bulk-only mass storage.
+ *
+ * Notice that no error is reported because if this fails, the error
+ * would reappear on next transaction somehow.
+ *
+ * @param dev Device to be reseted.
+ * @param bulk_in_idx Index of bulk in pipe.
+ * @param bulk_out_idx Index of bulk out pipe.
+ */
+void usb_massstor_reset_recovery(usb_device_t *dev,
+    size_t bulk_in_idx, size_t bulk_out_idx)
+{
+	/* We would ignore errors here because if this fails
+	 * we are doomed anyway and any following transaction would fail.
+	 */
+	usb_massstor_reset(dev);
+	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_in_idx].pipe);
+	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_out_idx].pipe);
+}
+
+/** Get max LUN of a mass storage device.
+ *
+ * @see usb_masstor_get_lun_count
+ *
+ * @warning Error from this command does not necessarily indicate malfunction
+ * of the device. Device does not need to support this request.
+ * You shall rather use usb_masstor_get_lun_count.
+ *
+ * @param dev Mass storage device.
+ * @return Error code of maximum LUN (index, not count).
+ */
+int usb_massstor_get_max_lun(usb_device_t *dev)
+{
+	uint8_t max_lun;
+	size_t data_recv_len;
+	int rc = usb_control_request_get(&dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
+	    0xFE, 0, dev->interface_no, &max_lun, 1, &data_recv_len);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (data_recv_len != 1) {
+		return EEMPTY;
+	}
+	return (int) max_lun;
+}
+
+/** Get number of LUNs supported by mass storage device.
+ *
+ * @warning This function hides any error during the request
+ * (typically that shall not be a problem).
+ *
+ * @param dev Mass storage device.
+ * @return Number of LUNs.
+ */
+size_t usb_masstor_get_lun_count(usb_device_t *dev)
+{
+	int max_lun = usb_massstor_get_max_lun(dev);
+	if (max_lun < 0) {
+		max_lun = 1;
+	} else {
+		max_lun++;
+	}
+
+	return (size_t) max_lun;
+}
+
 /**
  * @}
Index: uspace/drv/usbmast/mast.h
===================================================================
--- uspace/drv/usbmast/mast.h	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbmast/mast.h	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -40,7 +40,30 @@
 #include <usb/usb.h>
 #include <usb/pipes.h>
+#include <usb/devdrv.h>
 
-int usb_massstor_data_in(usb_pipe_t *, usb_pipe_t *, uint32_t, uint8_t,
-    void *, size_t, void *, size_t, size_t *);
+/** Result of SCSI INQUIRY command.
+ * This is already parsed structure, not the original buffer returned by
+ * the device.
+ */
+typedef struct {
+	/** SCSI peripheral device type. */
+	int peripheral_device_type;
+	/** Whether the device is removable. */
+	bool removable;
+	/** Vendor ID string. */
+	char vendor_id[9];
+	/** Product ID and product revision string. */
+	char product_and_revision[12];
+} usb_massstor_inquiry_result_t;
+
+int usb_massstor_data_in(usb_device_t *dev, size_t, size_t,
+    uint32_t, uint8_t, void *, size_t, void *, size_t, size_t *);
+int usb_massstor_reset(usb_device_t *);
+void usb_massstor_reset_recovery(usb_device_t *, size_t, size_t);
+int usb_massstor_get_max_lun(usb_device_t *);
+size_t usb_masstor_get_lun_count(usb_device_t *);
+int usb_massstor_inquiry(usb_device_t *, size_t, size_t,
+    usb_massstor_inquiry_result_t *);
+const char *usb_str_masstor_scsi_peripheral_device_type(int);
 
 #endif
Index: uspace/drv/usbmid/Makefile
===================================================================
--- uspace/drv/usbmid/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbmid/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,14 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+	
 BINARY = usbmid
 
Index: uspace/drv/usbmouse/Makefile
===================================================================
--- uspace/drv/usbmouse/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/usbmouse/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -28,6 +28,15 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+
+LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
 
 BINARY = usbmouse
Index: uspace/drv/vhc/Makefile
===================================================================
--- uspace/drv/vhc/Makefile	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/vhc/Makefile	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -29,4 +29,6 @@
 USPACE_PREFIX = ../..
 LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
 	$(LIBUSB_PREFIX)/libusb.a \
 	$(LIBUSBVIRT_PREFIX)/libusbvirt.a \
@@ -34,4 +36,6 @@
 EXTRA_CFLAGS += \
 	-I$(LIBUSBVIRT_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
 	-I$(LIBUSB_PREFIX)/include \
 	-I$(LIBDRV_PREFIX)/include
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/vhc/connhost.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -94,4 +94,20 @@
 }
 
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	VHC_DATA(vhc, fun);
+	bool found =
+	    usb_device_keeper_find_by_address(&vhc->dev_keeper, address, handle);
+	return found ? EOK : ENOENT;
+}
+
 /** Release previously requested address.
  *
@@ -444,4 +460,5 @@
 	.request_address = request_address,
 	.bind_address = bind_address,
+	.find_by_address = find_by_address,
 	.release_address = release_address,
 
Index: uspace/drv/vhc/main.c
===================================================================
--- uspace/drv/vhc/main.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/vhc/main.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -104,5 +104,11 @@
 	}
 
-	ddf_fun_add_to_class(hc, "usbhc");
+	rc = ddf_fun_add_to_class(hc, USB_HC_DDF_CLASS_NAME);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to add function to HC class: %s.\n",
+		    str_error(rc));
+		free(data);
+		return rc;
+	}
 
 	virtual_hub_device_init(hc);
Index: uspace/drv/vhc/transfer.c
===================================================================
--- uspace/drv/vhc/transfer.c	(revision 373bc2d9d2f348d908db35baafe480c948d98d0d)
+++ uspace/drv/vhc/transfer.c	(revision 9e195e2cd2e7af9bd0b0ef0bde139dac93b3f53f)
@@ -135,5 +135,4 @@
 		if (transfer->direction == USB_DIRECTION_IN) {
 			rc = usbvirt_ipc_send_control_read(phone,
-			    transfer->endpoint,
 			    transfer->setup_buffer, transfer->setup_buffer_size,
 			    transfer->data_buffer, transfer->data_buffer_size,
@@ -142,5 +141,4 @@
 			assert(transfer->direction == USB_DIRECTION_OUT);
 			rc = usbvirt_ipc_send_control_write(phone,
-			    transfer->endpoint,
 			    transfer->setup_buffer, transfer->setup_buffer_size,
 			    transfer->data_buffer, transfer->data_buffer_size);
