Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/Makefile	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -35,4 +35,5 @@
 	src/addrkeep.c \
 	src/class.c \
+	src/ddfiface.c \
 	src/debug.c \
 	src/dp.c \
Index: uspace/lib/usb/include/usb/ddfiface.h
===================================================================
--- uspace/lib/usb/include/usb/ddfiface.h	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
+++ uspace/lib/usb/include/usb/ddfiface.h	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -0,0 +1,58 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Implementations of DDF interfaces functions.
+ */
+#ifndef LIBUSB_DDFIFACE_H_
+#define LIBUSB_DDFIFACE_H_
+
+#include <sys/types.h>
+#include <usb/usbdevice.h>
+#include <usb_iface.h>
+
+int usb_iface_get_hc_handle_hub_impl(device_t *, devman_handle_t *);
+int usb_iface_get_address_hub_impl(device_t *, devman_handle_t,
+    usb_address_t *);
+extern usb_iface_t usb_iface_hub_impl;
+
+int usb_iface_get_hc_handle_hub_child_impl(device_t *, devman_handle_t *);
+int usb_iface_get_address_hub_child_impl(device_t *, devman_handle_t,
+    usb_address_t *);
+extern usb_iface_t usb_iface_hub_child_impl;
+
+int usb_iface_get_hc_handle_hc_impl(device_t *, devman_handle_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/dp.h
===================================================================
--- uspace/lib/usb/include/usb/dp.h	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/include/usb/dp.h	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -45,4 +45,6 @@
 } usb_dp_descriptor_nesting_t;
 
+extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
+
 typedef struct {
 	usb_dp_descriptor_nesting_t *nesting;
Index: uspace/lib/usb/include/usb/hub.h
===================================================================
--- uspace/lib/usb/include/usb/hub.h	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/include/usb/hub.h	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -39,4 +39,6 @@
 #include <usb/usbdevice.h>
 
+int usb_hc_new_device_wrapper(device_t *, usb_hc_connection_t *, usb_speed_t,
+    int (*)(int, void *), int, void *, usb_address_t *, devman_handle_t *);
 
 /** Info about device attached to host controller.
@@ -53,8 +55,8 @@
 } usb_hc_attached_device_t;
 
-int usb_hc_reserve_default_address(usb_hc_connection_t *, bool);
+int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);
 int usb_hc_release_default_address(usb_hc_connection_t *);
 
-usb_address_t usb_hc_request_address(usb_hc_connection_t *, bool);
+usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
 int usb_hc_register_device(usb_hc_connection_t *,
     const usb_hc_attached_device_t *);
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/include/usb/pipes.h	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -107,4 +107,6 @@
 	/** Endpoint description. */
 	const usb_endpoint_description_t *description;
+	/** Interface number the endpoint must belong to (-1 for any). */
+	const int interface_no;
 	/** Found descriptor fitting the description. */
 	usb_standard_endpoint_descriptor_t *descriptor;
@@ -121,4 +123,6 @@
 int usb_device_connection_initialize(usb_device_connection_t *,
     devman_handle_t, usb_address_t);
+
+int usb_device_get_assigned_interface(device_t *);
 
 int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *,
Index: uspace/lib/usb/include/usb/recognise.h
===================================================================
--- uspace/lib/usb/include/usb/recognise.h	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/include/usb/recognise.h	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -41,4 +41,8 @@
 #include <ipc/devman.h>
 
+int usb_device_create_match_ids_from_interface(
+    const usb_standard_device_descriptor_t *,
+    const usb_standard_interface_descriptor_t *, match_id_list_t *);
+
 int usb_device_create_match_ids(usb_endpoint_pipe_t *, match_id_list_t *);
 
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/include/usb/usb.h	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -68,4 +68,14 @@
 	USB_DIRECTION_BOTH
 } usb_direction_t;
+
+/** USB speeds. */
+typedef enum {
+	/** USB 1.1 low speed (1.5Mbits/s). */
+	USB_SPEED_LOW,
+	/** USB 1.1 full speed (12Mbits/s). */
+	USB_SPEED_FULL,
+	/** USB 2.0 high speed (480Mbits/s). */
+	USB_SPEED_HIGH
+} usb_speed_t;
 
 /** USB request type target. */
Index: uspace/lib/usb/include/usb/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/include/usb/usbdrv.h	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -103,7 +103,4 @@
 int usb_drv_create_match_ids_from_device_descriptor(match_id_list_t *,
     const usb_standard_device_descriptor_t *);
-int usb_drv_create_match_ids_from_configuration_descriptor(match_id_list_t *,
-    const void *, size_t);
-
 
 #endif
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
+++ uspace/lib/usb/src/ddfiface.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -0,0 +1,176 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Implementations of DDF interfaces functions (actual implementation).
+ */
+#include <ipc/devman.h>
+#include <usb/ddfiface.h>
+#include <errno.h>
+
+/** DDF interface for USB device, implementation for typical hub. */
+usb_iface_t  usb_iface_hub_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_impl,
+	.get_address = usb_iface_get_address_hub_impl
+};
+
+/** DDF interface for USB device, implementation for child of a typical hub. */
+usb_iface_t  usb_iface_hub_child_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
+	.get_address = usb_iface_get_address_hub_child_impl
+};
+
+
+/** Get host controller handle, interface implementation for hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Error code.
+ */
+int usb_iface_get_hc_handle_hub_impl(device_t *device, devman_handle_t *handle)
+{
+	assert(device);
+	return usb_hc_find(device->handle, handle);
+}
+
+/** Get host controller handle, interface implementation for child of
+ * a hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Error code.
+ */
+int usb_iface_get_hc_handle_hub_child_impl(device_t *device,
+    devman_handle_t *handle)
+{
+	assert(device);
+	device_t *parent = device->parent;
+
+	/* Default error, device does not support this operation. */
+	int rc = ENOTSUP;
+
+	if (parent && parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
+		usb_iface_t *usb_iface
+		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
+		assert(usb_iface != NULL);
+
+		if (usb_iface->get_hc_handle) {
+			rc = usb_iface->get_hc_handle(parent, handle);
+		}
+	}
+
+	return rc;
+}
+
+/** Get host controller handle, interface implementation for HC driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Always EOK.
+ */
+int usb_iface_get_hc_handle_hc_impl(device_t *device, devman_handle_t *handle)
+{
+	assert(device);
+
+	if (handle != NULL) {
+		*handle = device->handle;
+	}
+
+	return EOK;
+}
+
+/** Get USB device address, interface implementation for hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[in] handle Devman handle of USB device we want address of.
+ * @param[out] address Storage for USB address of device with handle @p handle.
+ * @return Error code.
+ */
+int usb_iface_get_address_hub_impl(device_t *device, devman_handle_t handle,
+    usb_address_t *address)
+{
+	assert(device);
+	int parent_phone = devman_parent_device_connect(device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	sysarg_t addr;
+	int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS, handle, &addr);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (address != NULL) {
+		*address = (usb_address_t) addr;
+	}
+
+	return EOK;
+}
+
+/** Get USB device address, interface implementation for child of
+ * a hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[in] handle Devman handle of USB device we want address of.
+ * @param[out] address Storage for USB address of device with handle @p handle.
+ * @return Error code.
+ */
+int usb_iface_get_address_hub_child_impl(device_t *device,
+    devman_handle_t handle, usb_address_t *address)
+{
+	assert(device);
+	device_t *parent = device->parent;
+
+	/* Default error, device does not support this operation. */
+	int rc = ENOTSUP;
+
+	if (parent && parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
+		usb_iface_t *usb_iface
+		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
+		assert(usb_iface != NULL);
+
+		if (usb_iface->get_address) {
+			rc = usb_iface->get_address(parent, handle, address);
+		}
+	}
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/dp.c
===================================================================
--- uspace/lib/usb/src/dp.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/src/dp.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -40,4 +40,25 @@
 #include <bool.h>
 #include <usb/dp.h>
+#include <usb/descriptor.h>
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+/** Nesting of standard USB descriptors. */
+usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+#undef NESTING
+#undef LAST_NESTING
 
 /** Tells whether pointer points inside descriptor data.
Index: uspace/lib/usb/src/hub.c
===================================================================
--- uspace/lib/usb/src/hub.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/src/hub.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -34,4 +34,7 @@
  */
 #include <usb/hub.h>
+#include <usb/pipes.h>
+#include <usb/request.h>
+#include <usb/recognise.h>
 #include <usbhc_iface.h>
 #include <errno.h>
@@ -56,5 +59,5 @@
  */
 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
-    bool full_speed)
+    usb_speed_t speed)
 {
 	CHECK_CONNECTION(connection);
@@ -62,5 +65,5 @@
 	return async_req_2_0(connection->hc_phone,
 	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, full_speed);
+	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
 }
 
@@ -85,5 +88,5 @@
  */
 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
-    bool full_speed)
+    usb_speed_t speed)
 {
 	CHECK_CONNECTION(connection);
@@ -92,5 +95,5 @@
 	int rc = async_req_2_1(connection->hc_phone,
 	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_REQUEST_ADDRESS, full_speed,
+	    IPC_M_USBHC_REQUEST_ADDRESS, speed,
 	    &address);
 	if (rc != EOK) {
@@ -138,4 +141,164 @@
 
 
+/** Wrapper for registering attached device to the hub.
+ *
+ * The @p enable_port function is expected to enable singalling on given
+ * port.
+ * The two arguments to it can have arbitrary meaning
+ * (the @p port_no is only a suggestion)
+ * and are not touched at all by this function
+ * (they are passed as is to the @p enable_port function).
+ *
+ * If the @p enable_port fails (i.e. does not return EOK), the device
+ * addition is cancelled.
+ * The return value is then returned (it is good idea to use different
+ * error codes than those listed as return codes by this function itself).
+ *
+ * @param parent Parent device (i.e. the hub device).
+ * @param connection Opened connection to host controller.
+ * @param dev_speed New device speed.
+ * @param enable_port Function for enabling signalling through the port the
+ *	device is attached to.
+ * @param port_no Port number (passed through to @p enable_port).
+ * @param arg Any data argument to @p enable_port.
+ * @param[out] assigned_address USB address of the device.
+ * @param[out] assigned_handle Devman handle of the new device.
+ * @return Error code.
+ * @retval ENOENT Connection to HC not opened.
+ * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
+ * @retval EBUSY Failed reserving default USB address.
+ * @retval ENOTCONN Problem connecting to the host controller via USB pipe.
+ * @retval ESTALL Problem communication with device (either SET_ADDRESS
+ *	request or requests for descriptors when creating match ids).
+ */
+int usb_hc_new_device_wrapper(device_t *parent, usb_hc_connection_t *connection,
+    usb_speed_t dev_speed,
+    int (*enable_port)(int port_no, void *arg), int port_no, void *arg,
+    usb_address_t *assigned_address, devman_handle_t *assigned_handle)
+{
+	CHECK_CONNECTION(connection);
+
+	/*
+	 * Request new address.
+	 */
+	usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed);
+	if (dev_addr < 0) {
+		return EADDRNOTAVAIL;
+	}
+
+	int rc;
+
+	/*
+	 * Reserve the default address.
+	 */
+	rc = usb_hc_reserve_default_address(connection, dev_speed);
+	if (rc != EOK) {
+		rc = EBUSY;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * Enable the port (i.e. allow signalling through this port).
+	 */
+	rc = enable_port(port_no, arg);
+	if (rc != EOK) {
+		goto leave_release_default_address;
+	}
+
+	/*
+	 * Change the address from default to the free one.
+	 * We need to create a new control pipe for that.
+	 */
+	usb_device_connection_t dev_conn;
+	rc = usb_device_connection_initialize_on_default_address(&dev_conn,
+	    connection);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	usb_endpoint_pipe_t ctrl_pipe;
+	rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
+	    &dev_conn);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	rc = usb_request_set_address(&ctrl_pipe, dev_addr);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_stop_session;
+	}
+
+	usb_endpoint_pipe_end_session(&ctrl_pipe);
+
+	/*
+	 * Once the address is changed, we can return the default address.
+	 */
+	usb_hc_release_default_address(connection);
+
+	/*
+	 * It is time to register the device with devman.
+	 */
+	/* FIXME: create device_register that will get opened ctrl pipe. */
+	devman_handle_t child_handle;
+	rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
+	    parent, &child_handle);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * And now inform the host controller about the handle.
+	 */
+	usb_hc_attached_device_t new_device = {
+		.address = dev_addr,
+		.handle = child_handle
+	};
+	rc = usb_hc_register_device(connection, &new_device);
+	if (rc != EOK) {
+		rc = EDESTADDRREQ;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * And we are done.
+	 */
+	if (assigned_address != NULL) {
+		*assigned_address = dev_addr;
+	}
+	if (assigned_handle != NULL) {
+		*assigned_handle = child_handle;
+	}
+
+	return EOK;
+
+
+
+	/*
+	 * Error handling (like nested exceptions) starts here.
+	 * Completely ignoring errors here.
+	 */
+
+leave_stop_session:
+	usb_endpoint_pipe_end_session(&ctrl_pipe);
+
+leave_release_default_address:
+	usb_hc_release_default_address(connection);
+
+leave_release_free_address:
+	usb_hc_unregister_device(connection, dev_addr);
+
+	return rc;
+}
+
 /**
  * @}
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/src/pipes.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -35,7 +35,55 @@
 #include <usb/usb.h>
 #include <usb/pipes.h>
+#include <usbhc_iface.h>
+#include <usb_iface.h>
 #include <errno.h>
 #include <assert.h>
-#include <usb/usbdrv.h>
+
+/** Tell USB address assigned to given device.
+ *
+ * @param phone Phone to parent device.
+ * @param dev Device in question.
+ * @return USB address or error code.
+ */
+static usb_address_t get_my_address(int phone, device_t *dev)
+{
+	sysarg_t address;
+	int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS,
+	    dev->handle, &address);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return (usb_address_t) address;
+}
+
+/** Tell USB interface assigned to given device.
+ *
+ * @param device Device in question.
+ * @return Interface number (negative code means any).
+ */
+int usb_device_get_assigned_interface(device_t *device)
+{
+	int parent_phone = devman_parent_device_connect(device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return -1;
+	}
+
+	sysarg_t iface_no;
+	int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_INTERFACE,
+	    device->handle, &iface_no);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return -1;
+	}
+
+	return (int) iface_no;
+}
 
 /** Initialize connection to USB device.
@@ -55,15 +103,16 @@
 	usb_address_t my_address;
 
-	rc = usb_drv_find_hc(device, &hc_handle);
+	rc = usb_hc_find(device->handle, &hc_handle);
 	if (rc != EOK) {
 		return rc;
 	}
 
-	int hc_phone = devman_device_connect(hc_handle, 0);
-	if (hc_phone < 0) {
-		return hc_phone;
-	}
-
-	my_address = usb_drv_get_my_address(hc_phone, device);
+	int parent_phone = devman_parent_device_connect(device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	my_address = get_my_address(parent_phone, device);
 	if (my_address < 0) {
 		rc = my_address;
@@ -75,5 +124,5 @@
 
 leave:
-	async_hangup(hc_phone);
+	async_hangup(parent_phone);
 	return rc;
 }
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/src/pipesinit.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -109,4 +109,5 @@
  * @param mapping_count Number of endpoint mappings in @p mapping.
  * @param found_endpoint Description of found endpoint.
+ * @param interface_number Number of currently processed interface.
  * @return Endpoint mapping corresponding to @p found_endpoint.
  * @retval NULL No corresponding endpoint found.
@@ -114,9 +115,15 @@
 static usb_endpoint_mapping_t *find_endpoint_mapping(
     usb_endpoint_mapping_t *mapping, size_t mapping_count,
-    usb_endpoint_description_t *found_endpoint)
+    usb_endpoint_description_t *found_endpoint,
+    int interface_number)
 {
 	while (mapping_count > 0) {
-		if (endpoint_fits_description(mapping->description,
-		    found_endpoint)) {
+		bool interface_number_fits = (mapping->interface_no < 0)
+		    || (mapping->interface_no == interface_number);
+
+		bool endpoint_descriptions_fits = endpoint_fits_description(
+		    mapping->description, found_endpoint);
+
+		if (interface_number_fits && endpoint_descriptions_fits) {
 			return mapping;
 		}
@@ -169,5 +176,5 @@
 	 */
 	usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping,
-	    mapping_count, &description);
+	    mapping_count, &description, interface->interface_number);
 	if (ep_mapping == NULL) {
 		return ENOENT;
Index: uspace/lib/usb/src/pipesio.c
===================================================================
--- uspace/lib/usb/src/pipesio.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/src/pipesio.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -71,4 +71,7 @@
 			ipc_method = IPC_M_USBHC_INTERRUPT_IN;
 			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_IN;
+			break;
 		default:
 			return ENOTSUP;
@@ -78,7 +81,8 @@
 	 * Make call identifying target USB device and type of transfer.
 	 */
-	aid_t opening_request = async_send_3(pipe->hc_phone,
+	aid_t opening_request = async_send_4(pipe->hc_phone,
 	    DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
 	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
 	    NULL);
 	if (opening_request == 0) {
@@ -194,4 +198,7 @@
 			ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
 			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_OUT;
+			break;
 		default:
 			return ENOTSUP;
@@ -201,7 +208,8 @@
 	 * Make call identifying target USB device and type of transfer.
 	 */
-	aid_t opening_request = async_send_3(pipe->hc_phone,
+	aid_t opening_request = async_send_4(pipe->hc_phone,
 	    DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
 	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
 	    NULL);
 	if (opening_request == 0) {
@@ -283,7 +291,8 @@
 	 * Make call identifying target USB device and control transfer type.
 	 */
-	aid_t opening_request = async_send_3(pipe->hc_phone,
+	aid_t opening_request = async_send_4(pipe->hc_phone,
 	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
 	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
 	    NULL);
 	if (opening_request == 0) {
@@ -402,8 +411,9 @@
 	 * Make call identifying target USB device and control transfer type.
 	 */
-	aid_t opening_request = async_send_4(pipe->hc_phone,
+	aid_t opening_request = async_send_5(pipe->hc_phone,
 	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
 	    pipe->wire->address, pipe->endpoint_no,
 	    data_buffer_size,
+	    pipe->max_packet_size,
 	    NULL);
 	if (opening_request == 0) {
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/src/recognise.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -34,8 +34,8 @@
  */
 #include <sys/types.h>
-#include <usb_iface.h>
 #include <usb/usbdrv.h>
 #include <usb/pipes.h>
 #include <usb/recognise.h>
+#include <usb/ddfiface.h>
 #include <usb/request.h>
 #include <usb/classes/classes.h>
@@ -46,36 +46,6 @@
 static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
 
-/** Callback for getting host controller handle.
- *
- * @param dev Device in question.
- * @param[out] handle Devman handle of the host controller.
- * @return Error code.
- */
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	assert(dev);
-	assert(dev->parent != NULL);
-
-	device_t *parent = dev->parent;
-
-	if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
-		usb_iface_t *usb_iface
-		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
-		assert(usb_iface != NULL);
-		if (usb_iface->get_hc_handle) {
-			int rc = usb_iface->get_hc_handle(parent, handle);
-			return rc;
-		}
-	}
-
-	return ENOTSUP;
-}
-
-static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle
-};
-
 device_ops_t child_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface
+	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
 };
 
@@ -142,4 +112,127 @@
 }
 
+#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
+	do { \
+		int __rc = usb_add_match_id((match_ids), (score), \
+		    format, ##__VA_ARGS__); \
+		if (__rc != EOK) { \
+			return __rc; \
+		} \
+	} while (0)
+
+/** Create device match ids based on its interface.
+ *
+ * @param[in] descriptor Interface descriptor.
+ * @param[out] matches Initialized list of match ids.
+ * @return Error code (the two mentioned are not the only ones).
+ * @retval EINVAL Invalid input parameters (expects non NULL pointers).
+ * @retval ENOENT Interface does not specify class.
+ */
+int usb_device_create_match_ids_from_interface(
+    const usb_standard_device_descriptor_t *desc_device,
+    const usb_standard_interface_descriptor_t *desc_interface,
+    match_id_list_t *matches)
+{
+	if (desc_interface == NULL) {
+		return EINVAL;
+	}
+	if (matches == NULL) {
+		return EINVAL;
+	}
+
+	if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {
+		return ENOENT;
+	}
+
+	const char *classname = usb_str_class(desc_interface->interface_class);
+	assert(classname != NULL);
+
+#define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"
+#define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \
+    desc_interface->interface_protocol
+
+#define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"
+#define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass
+
+#define IFACE_CLASS_FMT "interface&class=%s"
+#define IFACE_CLASS_ARGS classname
+
+#define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT
+#define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \
+    BCD_ARGS(desc_device->device_version)
+
+#define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"
+#define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id
+
+#define VENDOR_ONLY_FMT "vendor=0x%04x"
+#define VENDOR_ONLY_ARGS desc_device->vendor_id
+
+	/*
+	 * If the vendor is specified, create match ids with vendor with
+	 * higher score.
+	 * Then the same ones without the vendor part.
+	 */
+	if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {
+		/* First, interface matches with device release number. */
+		ADD_MATCHID_OR_RETURN(matches, 250,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 240,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 230,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);
+
+		/* Next, interface matches without release number. */
+		ADD_MATCHID_OR_RETURN(matches, 220,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 210,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 200,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);
+
+		/* Finally, interface matches with only vendor. */
+		ADD_MATCHID_OR_RETURN(matches, 190,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 180,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 170,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);
+	}
+
+	/* Now, the same but without any vendor specification. */
+	ADD_MATCHID_OR_RETURN(matches, 160,
+	    "usb&" IFACE_PROTOCOL_FMT,
+	    IFACE_PROTOCOL_ARGS);
+	ADD_MATCHID_OR_RETURN(matches, 150,
+	    "usb&" IFACE_SUBCLASS_FMT,
+	    IFACE_SUBCLASS_ARGS);
+	ADD_MATCHID_OR_RETURN(matches, 140,
+	    "usb&" IFACE_CLASS_FMT,
+	    IFACE_CLASS_ARGS);
+
+#undef IFACE_PROTOCOL_FMT
+#undef IFACE_PROTOCOL_ARGS
+#undef IFACE_SUBCLASS_FMT
+#undef IFACE_SUBCLASS_ARGS
+#undef IFACE_CLASS_FMT
+#undef IFACE_CLASS_ARGS
+#undef VENDOR_RELEASE_FMT
+#undef VENDOR_RELEASE_ARGS
+#undef VENDOR_PRODUCT_FMT
+#undef VENDOR_PRODUCT_ARGS
+#undef VENDOR_ONLY_FMT
+#undef VENDOR_ONLY_ARGS
+
+	return EOK;
+}
+
 /** Create DDF match ids from USB device descriptor.
  *
@@ -152,6 +245,4 @@
     const usb_standard_device_descriptor_t *device_descriptor)
 {
-	int rc;
-	
 	/*
 	 * Unless the vendor id is 0, the pair idVendor-idProduct
@@ -160,33 +251,26 @@
 	if (device_descriptor->vendor_id != 0) {
 		/* First, with release number. */
-		rc = usb_add_match_id(matches, 100,
+		ADD_MATCHID_OR_RETURN(matches, 100,
 		    "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
 		    (int) device_descriptor->vendor_id,
 		    (int) device_descriptor->product_id,
 		    BCD_ARGS(device_descriptor->device_version));
-		if (rc != EOK) {
-			return rc;
-		}
 		
 		/* Next, without release number. */
-		rc = usb_add_match_id(matches, 90,
+		ADD_MATCHID_OR_RETURN(matches, 90,
 		    "usb&vendor=0x%04x&product=0x%04x",
 		    (int) device_descriptor->vendor_id,
 		    (int) device_descriptor->product_id);
-		if (rc != EOK) {
-			return rc;
-		}
 	}	
 
 	/*
 	 * If the device class points to interface we skip adding
-	 * class directly.
+	 * class directly but we add a multi interface device.
 	 */
 	if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
-		rc = usb_add_match_id(matches, 50, "usb&class=%s",
+		ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
 		    usb_str_class(device_descriptor->device_class));
-		if (rc != EOK) {
-			return rc;
-		}
+	} else {
+		ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
 	}
 	
@@ -194,108 +278,4 @@
 }
 
-/** Create DDF match ids from USB configuration descriptor.
- * The configuration descriptor is expected to be in the complete form,
- * i.e. including interface, endpoint etc. descriptors.
- *
- * @param matches List of match ids to extend.
- * @param config_descriptor Configuration descriptor returned by given device.
- * @param total_size Size of the @p config_descriptor.
- * @return Error code.
- */
-int usb_drv_create_match_ids_from_configuration_descriptor(
-    match_id_list_t *matches,
-    const void *config_descriptor, size_t total_size)
-{
-	/*
-	 * Iterate through config descriptor to find the interface
-	 * descriptors.
-	 */
-	size_t position = sizeof(usb_standard_configuration_descriptor_t);
-	while (position + 1 < total_size) {
-		uint8_t *current_descriptor
-		    = ((uint8_t *) config_descriptor) + position;
-		uint8_t cur_descr_len = current_descriptor[0];
-		uint8_t cur_descr_type = current_descriptor[1];
-
-		if (cur_descr_len == 0) {
-			return ENOENT;
-		}
-		
-		position += cur_descr_len;
-		
-		if (cur_descr_type != USB_DESCTYPE_INTERFACE) {
-			continue;
-		}
-		
-		/*
-		 * Finally, we found an interface descriptor.
-		 */
-		usb_standard_interface_descriptor_t *interface
-		    = (usb_standard_interface_descriptor_t *)
-		    current_descriptor;
-		
-		int rc = usb_add_match_id(matches, 50,
-		    "usb&interface&class=%s",
-		    usb_str_class(interface->interface_class));
-		if (rc != EOK) {
-			return rc;
-		}
-	}
-	
-	return EOK;
-}
-
-/** Add match ids based on configuration descriptor.
- *
- * @param pipe Control pipe to the device.
- * @param matches Match ids list to add matches to.
- * @param config_count Number of configurations the device has.
- * @return Error code.
- */
-static int usb_add_config_descriptor_match_ids(usb_endpoint_pipe_t *pipe,
-    match_id_list_t *matches, int config_count)
-{
-	int final_rc = EOK;
-	
-	int config_index;
-	for (config_index = 0; config_index < config_count; config_index++) {
-		int rc;
-		usb_standard_configuration_descriptor_t config_descriptor;
-		rc = usb_request_get_bare_configuration_descriptor(pipe,
-		    config_index, &config_descriptor);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-
-		size_t full_config_descriptor_size;
-		void *full_config_descriptor
-		    = malloc(config_descriptor.total_length);
-		rc = usb_request_get_full_configuration_descriptor(pipe,
-		    config_index,
-		    full_config_descriptor, config_descriptor.total_length,
-		    &full_config_descriptor_size);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-		if (full_config_descriptor_size
-		    != config_descriptor.total_length) {
-			final_rc = ERANGE;
-			continue;
-		}
-		
-		rc = usb_drv_create_match_ids_from_configuration_descriptor(
-		    matches,
-		    full_config_descriptor, full_config_descriptor_size);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-		
-	}
-	
-	return final_rc;
-}
 
 /** Create match ids describing attached device.
@@ -330,20 +310,7 @@
 
 	/*
-	 * Go through all configurations and add matches
-	 * based on interface class.
-	 */
-	rc = usb_add_config_descriptor_match_ids(ctrl_pipe, matches,
-	    device_descriptor.configuration_count);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/*
 	 * As a fallback, provide the simplest match id possible.
 	 */
-	rc = usb_add_match_id(matches, 1, "usb&fallback");
-	if (rc != EOK) {
-		return rc;
-	}
+	ADD_MATCHID_OR_RETURN(matches, 1, "usb&fallback");
 
 	return EOK;
Index: uspace/lib/usb/src/usbdrv.c
===================================================================
--- uspace/lib/usb/src/usbdrv.c	(revision 6bb83c7617113ccde4bfaaec20df6a91f8b48ebd)
+++ uspace/lib/usb/src/usbdrv.c	(revision da7c0a9991263785d7e76b1441cee6cd6cd1950a)
@@ -34,28 +34,6 @@
  */
 #include <usb/usbdrv.h>
-#include <usbhc_iface.h>
-#include <usb_iface.h>
 #include <errno.h>
-#include <str_error.h>
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Phone to host controller driver. */
-	int phone;
-	/** Data buffer. */
-	void *buffer;
-	/** Buffer size. */
-	size_t size;
-	/** Storage for actual number of bytes transferred. */
-	size_t *size_transferred;
-	/** Initial call reply data. */
-	ipc_call_t reply;
-	/** Initial call identifier. */
-	aid_t request;
-	/** Reply data for data read call. */
-	ipc_call_t read_reply;
-	/** Data read call identifier. */
-	aid_t read_request;
-} transfer_info_t;
+
 
 /** Find handle of host controller the device is physically attached to.
@@ -67,30 +45,5 @@
 int usb_drv_find_hc(device_t *dev, devman_handle_t *handle)
 {
-	if (dev == NULL) {
-		return EBADMEM;
-	}
-	if (handle == NULL) {
-		return EBADMEM;
-	}
-
-	int parent_phone = devman_parent_device_connect(dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (parent_phone < 0) {
-		return parent_phone;
-	}
-
-	devman_handle_t h;
-	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
-
-	async_hangup(parent_phone);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	*handle = h;
-
-	return EOK;
+	return ENOTSUP;
 }
 
@@ -105,5 +58,5 @@
     unsigned int flags)
 {
-	return devman_device_connect(hc_handle, flags);
+	return ENOTSUP;
 }
 
@@ -116,16 +69,5 @@
 int usb_drv_hc_connect_auto(device_t *dev, unsigned int flags)
 {
-	int rc;
-	devman_handle_t hc_handle;
-
-	/*
-	 * Call parent hub to obtain device handle of respective HC.
-	 */
-	rc = usb_drv_find_hc(dev, &hc_handle);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	return usb_drv_hc_connect(dev, hc_handle, flags);
+	return ENOTSUP;
 }
 
@@ -138,14 +80,5 @@
 usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
 {
-	sysarg_t address;
-	int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_GET_ADDRESS,
-	    dev->handle, &address);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	return (usb_address_t) address;
+	return ENOTSUP;
 }
 
@@ -157,6 +90,5 @@
 int usb_drv_reserve_default_address(int phone)
 {
-	return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS);
+	return ENOTSUP;
 }
 
@@ -168,6 +100,5 @@
 int usb_drv_release_default_address(int phone)
 {
-	return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
+	return ENOTSUP;
 }
 
@@ -179,12 +110,5 @@
 usb_address_t usb_drv_request_address(int phone)
 {
-	sysarg_t address;
-	int rc = async_req_1_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_REQUEST_ADDRESS, &address);
-	if (rc != EOK) {
-		return rc;
-	} else {
-		return (usb_address_t) address;
-	}
+	return ENOTSUP;
 }
 
@@ -199,9 +123,5 @@
     devman_handle_t handle)
 {
-	int rc = async_req_3_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_BIND_ADDRESS,
-	    address, handle);
-
-	return rc;
+	return ENOTSUP;
 }
 
@@ -214,132 +134,6 @@
 int usb_drv_release_address(int phone, usb_address_t address)
 {
-	return async_req_2_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RELEASE_ADDRESS, address);
-}
-
-/** Send data to HCD.
- *
- * @param phone Phone to HC.
- * @param method Method used for calling.
- * @param target Targeted device.
- * @param buffer Data buffer (NULL to skip data transfer phase).
- * @param size Buffer size (must be zero when @p buffer is NULL).
- * @param handle Storage for transaction handle (cannot be NULL).
- * @return Error status.
- * @retval EINVAL Invalid parameter.
- * @retval ENOMEM Not enough memory to complete the operation.
- */
-static int async_send_buffer(int phone, int method,
-    usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-
-	if ((buffer == NULL) && (size > 0)) {
-		return EINVAL;
-	}
-
-	if (handle == NULL) {
-		return EINVAL;
-	}
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->read_request = 0;
-	transfer->size_transferred = NULL;
-	transfer->buffer = NULL;
-	transfer->size = 0;
-	transfer->phone = phone;
-
-	int rc;
-
-	transfer->request = async_send_4(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    method,
-	    target.address, target.endpoint,
-	    size,
-	    &transfer->reply);
-
-	if (size > 0) {
-		rc = async_data_write_start(phone, buffer, size);
-		if (rc != EOK) {
-			async_wait_for(transfer->request, NULL);
-			return rc;
-		}
-	}
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
-}
-
-/** Prepare data retrieval.
- *
- * @param phone Opened phone to HCD.
- * @param method Method used for calling.
- * @param target Targeted device.
- * @param buffer Buffer where to store retrieved data
- * 	(NULL to skip data transfer phase).
- * @param size Buffer size (must be zero when @p buffer is NULL).
- * @param actual_size Storage where actual number of bytes transferred will
- * 	be stored.
- * @param handle Storage for transaction handle (cannot be NULL).
- * @return Error status.
- * @retval EINVAL Invalid parameter.
- * @retval ENOMEM Not enough memory to complete the operation.
- */
-static int async_recv_buffer(int phone, int method,
-    usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-
-	if ((buffer == NULL) && (size > 0)) {
-		return EINVAL;
-	}
-
-	if (handle == NULL) {
-		return EINVAL;
-	}
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->read_request = 0;
-	transfer->size_transferred = actual_size;
-	transfer->buffer = buffer;
-	transfer->size = size;
-	transfer->phone = phone;
-
-	transfer->request = async_send_4(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    method,
-	    target.address, target.endpoint,
-	    size,
-	    &transfer->reply);
-
-	if (buffer != NULL) {
-		transfer->read_request = async_data_read(phone, buffer, size,
-		    &transfer->read_reply);
-	}
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
-}
-
+	return ENOTSUP;
+}
 
 /** Blocks caller until given USB transaction is finished.
@@ -355,42 +149,5 @@
 int usb_drv_async_wait_for(usb_handle_t handle)
 {
-	if (handle == 0) {
-		return EBADMEM;
-	}
-
-	int rc = EOK;
-
-	transfer_info_t *transfer = (transfer_info_t *) handle;
-
-	sysarg_t answer_rc;
-
-	/*
-	 * If the buffer is not NULL, we must accept some data.
-	 */
-	if ((transfer->buffer != NULL) && (transfer->size > 0)) {
-		async_wait_for(transfer->read_request, &answer_rc);
-
-		if (answer_rc != EOK) {
-			rc = (int) answer_rc;
-			goto leave;
-		}
-
-		if (transfer->size_transferred != NULL) {
-			*(transfer->size_transferred)
-			    = IPC_GET_ARG2(transfer->read_reply);
-		}
-	}
-
-	async_wait_for(transfer->request, &answer_rc);
-
-	if (answer_rc != EOK) {
-		rc = (int) answer_rc;
-		goto leave;
-	}
-
-leave:
-	free(transfer);
-
-	return rc;
+	return ENOTSUP;
 }
 
@@ -400,9 +157,5 @@
     usb_handle_t *handle)
 {
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_INTERRUPT_OUT,
-	    target,
-	    buffer, size,
-	    handle);
+	return ENOTSUP;
 }
 
@@ -412,9 +165,5 @@
     usb_handle_t *handle)
 {
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_INTERRUPT_IN,
-	    target,
-	    buffer, size, actual_size,
-	    handle);
+	return ENOTSUP;
 }
 
@@ -424,9 +173,5 @@
     usb_handle_t *handle)
 {
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_SETUP,
-	    target,
-	    buffer, size,
-	    handle);
+	return ENOTSUP;
 }
 
@@ -436,9 +181,5 @@
     usb_handle_t *handle)
 {
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_DATA,
-	    target,
-	    buffer, size,
-	    handle);
+	return ENOTSUP;
 }
 
@@ -447,9 +188,5 @@
     usb_handle_t *handle)
 {
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_STATUS,
-	    target,
-	    NULL, 0, NULL,
-	    handle);
+	return ENOTSUP;
 }
 
@@ -460,49 +197,5 @@
     usb_handle_t *handle)
 {
-	// FIXME - check input parameters instead of asserting them
-	assert(phone > 0);
-	assert(setup_packet != NULL);
-	assert(setup_packet_size > 0);
-	assert(((buffer != NULL) && (buffer_size > 0))
-	    || ((buffer == NULL) && (buffer_size == 0)));
-	assert(handle != NULL);
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->read_request = 0;
-	transfer->size_transferred = NULL;
-	transfer->buffer = NULL;
-	transfer->size = 0;
-	transfer->phone = phone;
-
-	int rc;
-
-	transfer->request = async_send_3(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_CONTROL_WRITE,
-	    target.address, target.endpoint,
-	    &transfer->reply);
-
-	rc = async_data_write_start(phone, setup_packet, setup_packet_size);
-	if (rc != EOK) {
-		async_wait_for(transfer->request, NULL);
-		return rc;
-	}
-
-	if (buffer_size > 0) {
-		rc = async_data_write_start(phone, buffer, buffer_size);
-		if (rc != EOK) {
-			async_wait_for(transfer->request, NULL);
-			return rc;
-		}
-	}
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
+	return ENOTSUP;
 }
 
@@ -512,9 +205,5 @@
     usb_handle_t *handle)
 {
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_SETUP,
-	    target,
-	    buffer, size,
-	    handle);
+	return ENOTSUP;
 }
 
@@ -524,9 +213,5 @@
     usb_handle_t *handle)
 {
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_DATA,
-	    target,
-	    buffer, size, actual_size,
-	    handle);
+	return ENOTSUP;
 }
 
@@ -535,9 +220,5 @@
     usb_handle_t *handle)
 {
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_STATUS,
-	    target,
-	    NULL, 0,
-	    handle);
+	return ENOTSUP;
 }
 
@@ -548,44 +229,5 @@
     usb_handle_t *handle)
 {
-	// FIXME - check input parameters instead of asserting them
-	assert(phone > 0);
-	assert(setup_packet != NULL);
-	assert(setup_packet_size > 0);
-	assert(buffer != NULL);
-	assert(buffer_size > 0);
-	assert(handle != NULL);
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->size_transferred = actual_size;
-	transfer->buffer = buffer;
-	transfer->size = buffer_size;
-	transfer->phone = phone;
-
-	int rc;
-
-	transfer->request = async_send_4(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_CONTROL_READ,
-	    target.address, target.endpoint,
-	    buffer_size,
-	    &transfer->reply);
-
-	rc = async_data_write_start(phone, setup_packet, setup_packet_size);
-	if (rc != EOK) {
-		async_wait_for(transfer->request, NULL);
-		return rc;
-	}
-
-	transfer->read_request = async_data_read(phone, buffer, buffer_size,
-	    &transfer->read_reply);
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
+	return ENOTSUP;
 }
 
