Index: uspace/lib/usb/include/usb/devdrv.h
===================================================================
--- uspace/lib/usb/include/usb/devdrv.h	(revision bb18a59f3583290fcab2f1c1467bc35c4416c83a)
+++ uspace/lib/usb/include/usb/devdrv.h	(revision 7526e3d9dbfa6a43fb1014e632caa2fbe206bd0b)
@@ -47,4 +47,27 @@
 } usb_device_descriptors_t;
 
+/** Wrapper for data related to alternate interface setting.
+ * The pointers will typically point inside configuration descriptor and
+ * thus you shall not deallocate them.
+ */
+typedef struct {
+	/** Interface descriptor. */
+	usb_standard_interface_descriptor_t *interface;
+	/** Pointer to start of descriptor tree bound with this interface. */
+	uint8_t *nested_descriptors;
+	/** Size of data pointed by nested_descriptors in bytes. */
+	size_t nested_descriptors_size;
+} usb_alternate_interface_descriptors_t;
+
+/** Alternate interface settings. */
+typedef struct {
+	/** Array of alternate interfaces descriptions. */
+	usb_alternate_interface_descriptors_t *alternatives;
+	/** Size of @c alternatives array. */
+	size_t alternative_count;
+	/** Index of currently selected one. */
+	size_t current;
+} usb_alternate_interfaces_t;
+
 /** USB device structure. */
 typedef struct {
@@ -61,4 +84,10 @@
 	 */
 	int interface_no;
+
+	/** Alternative interfaces.
+	 * Set to NULL when the driver controls whole device
+	 * (i.e. more (or any) interfaces).
+	 */
+	usb_alternate_interfaces_t *alternate_interfaces;
 
 	/** Some useful descriptors. */
@@ -132,5 +161,4 @@
 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
 
-
 int usb_device_auto_poll(usb_device_t *, size_t,
     usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
Index: uspace/lib/usb/src/devdrv.c
===================================================================
--- uspace/lib/usb/src/devdrv.c	(revision bb18a59f3583290fcab2f1c1467bc35c4416c83a)
+++ uspace/lib/usb/src/devdrv.c	(revision 7526e3d9dbfa6a43fb1014e632caa2fbe206bd0b)
@@ -36,4 +36,5 @@
 #include <usb/request.h>
 #include <usb/debug.h>
+#include <usb/dp.h>
 #include <errno.h>
 #include <str_error.h>
@@ -275,4 +276,128 @@
 }
 
+/** Count number of alternate settings of a interface.
+ *
+ * @param config_descr Full configuration descriptor.
+ * @param config_descr_size Size of @p config_descr in bytes.
+ * @param interface_no Interface number.
+ * @return Number of alternate interfaces for @p interface_no interface.
+ */
+static size_t count_alternate_interfaces(uint8_t *config_descr,
+    size_t config_descr_size, int interface_no)
+{
+	assert(config_descr != NULL);
+	usb_dp_parser_t dp_parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+	usb_dp_parser_data_t dp_data = {
+		.data = config_descr,
+		.size = config_descr_size,
+		.arg = NULL
+	};
+
+	size_t alternate_count = 0;
+
+	uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
+	    &dp_data, config_descr);
+	while (iface_ptr != NULL) {
+		usb_standard_interface_descriptor_t *iface
+		    = (usb_standard_interface_descriptor_t *) iface_ptr;
+		if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
+			if (iface->interface_number == interface_no) {
+				alternate_count++;
+			}
+		}
+		iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
+		    config_descr, iface_ptr);
+	}
+
+	return alternate_count;
+}
+
+/** Initialize structures related to alternate interfaces.
+ *
+ * @param dev Device where alternate settings shall be initialized.
+ * @return Error code.
+ */
+static int initialize_alternate_interfaces(usb_device_t *dev)
+{
+	if (dev->interface_no < 0) {
+		dev->alternate_interfaces = NULL;
+		return EOK;
+	}
+
+	usb_alternate_interfaces_t *alternates
+	    = malloc(sizeof(usb_alternate_interfaces_t));
+
+	if (alternates == NULL) {
+		return ENOMEM;
+	}
+
+	alternates->alternative_count
+	    = count_alternate_interfaces(dev->descriptors.configuration,
+	    dev->descriptors.configuration_size, dev->interface_no);
+
+	if (alternates->alternative_count == 0) {
+		free(alternates);
+		return ENOENT;
+	}
+
+	alternates->alternatives = malloc(alternates->alternative_count
+	    * sizeof(usb_alternate_interface_descriptors_t));
+	if (alternates->alternatives == NULL) {
+		free(alternates);
+		return ENOMEM;
+	}
+
+	alternates->current = 0;
+
+	usb_dp_parser_t dp_parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+	usb_dp_parser_data_t dp_data = {
+		.data = dev->descriptors.configuration,
+		.size = dev->descriptors.configuration_size,
+		.arg = NULL
+	};
+
+	usb_alternate_interface_descriptors_t *cur_alt_iface
+	    = &alternates->alternatives[0];
+
+	uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
+	    &dp_data, dp_data.data);
+	while (iface_ptr != NULL) {
+		usb_standard_interface_descriptor_t *iface
+		    = (usb_standard_interface_descriptor_t *) iface_ptr;
+		if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
+		    || (iface->interface_number != dev->interface_no)) {
+			iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
+			    &dp_data,
+			    dp_data.data, iface_ptr);
+			continue;
+		}
+
+		cur_alt_iface->interface = iface;
+		cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
+
+		/* Find next interface to count size of nested descriptors. */
+		iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
+		    dp_data.data, iface_ptr);
+		if (iface_ptr == NULL) {
+			uint8_t *next = dp_data.data + dp_data.size;
+			cur_alt_iface->nested_descriptors_size
+			    = next - cur_alt_iface->nested_descriptors;
+		} else {
+			cur_alt_iface->nested_descriptors_size
+			    = iface_ptr - cur_alt_iface->nested_descriptors;
+		}
+
+		cur_alt_iface++;
+	}
+
+	dev->alternate_interfaces = alternates;
+
+	return EOK;
+}
+
 /** Callback when new device is supposed to be controlled by this driver.
  *
@@ -309,4 +434,6 @@
 	}
 
+	(void) initialize_alternate_interfaces(dev);
+
 	return driver->ops->add_device(dev);
 }
