Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/Makefile	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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 ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
+++ uspace/lib/usb/include/usb/ddfiface.h	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/include/usb/dp.h	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/include/usb/pipes.h	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/include/usb/recognise.h	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/include/usb/usbdrv.h	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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 ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
+++ uspace/lib/usb/src/ddfiface.c	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/src/dp.c	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/src/hub.c	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -301,5 +301,4 @@
 }
 
-
 /**
  * @}
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/src/pipes.c	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -36,4 +36,5 @@
 #include <usb/pipes.h>
 #include <usbhc_iface.h>
+#include <usb_iface.h>
 #include <errno.h>
 #include <assert.h>
@@ -41,5 +42,5 @@
 /** Tell USB address assigned to given device.
  *
- * @param phone Phone to my HC.
+ * @param phone Phone to parent device.
  * @param dev Device in question.
  * @return USB address or error code.
@@ -48,6 +49,6 @@
 {
 	sysarg_t address;
-	int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_GET_ADDRESS,
+	int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS,
 	    dev->handle, &address);
 
@@ -57,4 +58,31 @@
 
 	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;
 }
 
@@ -80,10 +108,11 @@
 	}
 
-	int hc_phone = devman_device_connect(hc_handle, 0);
-	if (hc_phone < 0) {
-		return hc_phone;
-	}
-
-	my_address = 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;
@@ -95,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 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/src/pipesinit.c	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/src/pipesio.c	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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;
@@ -194,4 +197,7 @@
 		case USB_TRANSFER_INTERRUPT:
 			ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
+			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_OUT;
 			break;
 		default:
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision 62066b4b9236cbb36a30b4ca96c26e641093692c)
+++ uspace/lib/usb/src/recognise.c	(revision ace12560c8fb7ffd6badf7674cbb3f68e1f1cee8)
@@ -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;
