Index: uspace/lib/usb/include/usb/devreq.h
===================================================================
--- uspace/lib/usb/include/usb/devreq.h	(revision 6986418a911da2a0d9bbcff0c77f11874afbefb6)
+++ uspace/lib/usb/include/usb/devreq.h	(revision f40131243ad1635ce6cd59eaf5a91902710c0306)
@@ -85,5 +85,14 @@
 } __attribute__ ((packed)) usb_device_request_setup_packet_t;
 
+
+int usb_drv_req_get_status(int, usb_address_t, usb_request_recipient_t,
+    uint16_t, uint16_t *);
+int usb_drv_req_clear_feature(int, usb_address_t, usb_request_recipient_t,
+    uint16_t, uint16_t);
+int usb_drv_req_set_feature(int, usb_address_t, usb_request_recipient_t,
+    uint16_t, uint16_t);
 int usb_drv_req_set_address(int, usb_address_t, usb_address_t);
+int usb_drv_req_get_descriptor(int, usb_address_t, usb_request_type_t,
+    uint8_t, uint8_t, uint16_t, void *, size_t, size_t *);
 int usb_drv_req_get_device_descriptor(int, usb_address_t,
     usb_standard_device_descriptor_t *);
@@ -92,5 +101,10 @@
 int usb_drv_req_get_full_configuration_descriptor(int, usb_address_t, int,
     void *, size_t, size_t *);
-
+int usb_drv_req_set_descriptor(int, usb_address_t, uint8_t, uint8_t, uint16_t,
+    void *, size_t);
+int usb_drv_req_get_configuration(int, usb_address_t, uint8_t *);
+int usb_drv_req_set_configuration(int, usb_address_t, uint8_t);
+int usb_drv_req_get_interface(int, usb_address_t, uint16_t, uint8_t *);
+int usb_drv_req_set_interface(int, usb_address_t, uint16_t, uint8_t);
 
 #endif
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 6986418a911da2a0d9bbcff0c77f11874afbefb6)
+++ uspace/lib/usb/include/usb/usb.h	(revision f40131243ad1635ce6cd59eaf5a91902710c0306)
@@ -54,4 +54,18 @@
 	USB_DIRECTION_OUT
 } usb_direction_t;
+
+/** USB request type target. */
+typedef enum {
+	USB_REQUEST_TYPE_STANDARD = 0,
+	USB_REQUEST_TYPE_CLASS = 1,
+	USB_REQUEST_TYPE_VENDOR = 2
+} usb_request_type_t;
+
+/** USB request recipient. */
+typedef enum {
+	USB_REQUEST_RECIPIENT_DEVICE = 0,
+	USB_REQUEST_RECIPIENT_INTERFACE = 1,
+	USB_REQUEST_RECIPIENT_ENDPOINT = 2
+} usb_request_recipient_t;
 
 /** USB transaction outcome. */
Index: uspace/lib/usb/include/usb/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision 6986418a911da2a0d9bbcff0c77f11874afbefb6)
+++ uspace/lib/usb/include/usb/usbdrv.h	(revision f40131243ad1635ce6cd59eaf5a91902710c0306)
@@ -96,4 +96,9 @@
 int usb_drv_async_wait_for(usb_handle_t);
 
+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);
+
 int usb_drv_create_device_match_ids(int, match_id_list_t *, usb_address_t);
 int usb_drv_register_child_in_devman(int, device_t *, usb_address_t,
Index: uspace/lib/usb/src/addrkeep.c
===================================================================
--- uspace/lib/usb/src/addrkeep.c	(revision 6986418a911da2a0d9bbcff0c77f11874afbefb6)
+++ uspace/lib/usb/src/addrkeep.c	(revision f40131243ad1635ce6cd59eaf5a91902710c0306)
@@ -187,4 +187,8 @@
 		new_address_position = addresses->used_addresses.next;
 	} else {
+		usb_address_keeping_used_t *first
+		    = used_address_get_instance(addresses->used_addresses.next);
+		previous_address = first->address;
+		
 		for_all_used_addresses(new_address_position, addresses) {
 			usb_address_keeping_used_t *info
@@ -194,4 +198,5 @@
 				break;
 			}
+			previous_address = info->address;
 		}
 
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision 6986418a911da2a0d9bbcff0c77f11874afbefb6)
+++ uspace/lib/usb/src/recognise.c	(revision f40131243ad1635ce6cd59eaf5a91902710c0306)
@@ -129,4 +129,103 @@
 }
 
+/** Create DDF match ids from USB device descriptor.
+ *
+ * @param matches List of match ids to extend.
+ * @param device_descriptor Device descriptor returned by given device.
+ * @return Error code.
+ */
+int usb_drv_create_match_ids_from_device_descriptor(
+    match_id_list_t *matches,
+    const usb_standard_device_descriptor_t *device_descriptor)
+{
+	int rc;
+	
+	/*
+	 * Unless the vendor id is 0, the pair idVendor-idProduct
+	 * quite uniquely describes the device.
+	 */
+	if (device_descriptor->vendor_id != 0) {
+		/* First, with release number. */
+		rc = usb_add_match_id(matches, 100,
+		    "usb&vendor=%d&product=%d&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, "usb&vendor=%d&product=%d",
+		    (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.
+	 */
+	if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
+		rc = usb_add_match_id(matches, 50, "usb&class=%s",
+		    usb_str_class(device_descriptor->device_class));
+		if (rc != EOK) {
+			return rc;
+		}
+	}
+	
+	return EOK;
+}
+
+/** 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];
+		
+		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.
  *
@@ -169,36 +268,13 @@
 			continue;
 		}
-
-		/*
-		 * Iterate through config descriptor to find the interface
-		 * descriptors.
-		 */
-		size_t position = sizeof(config_descriptor);
-		while (position + 1 < full_config_descriptor_size) {
-			uint8_t *current_descriptor
-			    = ((uint8_t *) full_config_descriptor) + position;
-			uint8_t cur_descr_len = current_descriptor[0];
-			uint8_t cur_descr_type = current_descriptor[1];
-			
-			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;
-			
-			rc = usb_add_match_id(matches, 50,
-			    "usb&interface&class=%s",
-			    usb_str_class(interface->interface_class));
-			if (rc != EOK) {
-				final_rc = rc;
-				break;
-			}
-		}
+		
+		rc = usb_drv_create_match_ids_from_configuration_descriptor(
+		    matches,
+		    full_config_descriptor, full_config_descriptor_size);
+		if (rc != EOK) {
+			final_rc = rc;
+			continue;
+		}
+		
 	}
 	
@@ -220,4 +296,8 @@
 {
 	int rc;
+	
+	/*
+	 * Retrieve device descriptor and add matches from it.
+	 */
 	usb_standard_device_descriptor_t device_descriptor;
 
@@ -227,41 +307,11 @@
 		return rc;
 	}
-
-	/*
-	 * Unless the vendor id is 0, the pair idVendor-idProduct
-	 * quite uniquely describes the device.
-	 */
-	if (device_descriptor.vendor_id != 0) {
-		/* First, with release number. */
-		rc = usb_add_match_id(matches, 100,
-		    "usb&vendor=%d&product=%d&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, "usb&vendor=%d&product=%d",
-		    (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.
-	 */
-	if (device_descriptor.device_class != USB_CLASS_USE_INTERFACE) {
-		rc = usb_add_match_id(matches, 50, "usb&class=%s",
-		    usb_str_class(device_descriptor.device_class));
-		if (rc != EOK) {
-			return rc;
-		}
-	}
+	
+	rc = usb_drv_create_match_ids_from_device_descriptor(matches,
+	    &device_descriptor);
+	if (rc != EOK) {
+		return rc;
+	}
+	
 	/*
 	 * Go through all configurations and add matches
Index: uspace/lib/usb/src/usbdrvreq.c
===================================================================
--- uspace/lib/usb/src/usbdrvreq.c	(revision 6986418a911da2a0d9bbcff0c77f11874afbefb6)
+++ uspace/lib/usb/src/usbdrvreq.c	(revision f40131243ad1635ce6cd59eaf5a91902710c0306)
@@ -36,4 +36,146 @@
 #include <errno.h>
 
+/**  Prepare USB target for control endpoint.
+ *
+ * @param name Variable name with the USB target.
+ * @param target_address Target USB address.
+ */
+#define PREPARE_TARGET(name, target_address) \
+	usb_target_t name = { \
+		.address = target_address, \
+		.endpoint = 0 \
+	}
+
+/** Prepare setup packet.
+ *
+ * @param name Variable name with the setup packet.
+ * @param p_direction Data transfer direction.
+ * @param p_type Request type (standard/class/vendor)
+ * @param p_recipient Recipient of the request.
+ * @param p_request Request.
+ * @param p_value wValue field of setup packet.
+ * @param p_index wIndex field of setup packet.
+ * @param p_length Length of extra data.
+ */
+#define PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
+    p_request, p_value, p_index, p_length) \
+	usb_device_request_setup_packet_t setup_packet = { \
+		.request_type = \
+			((p_direction) == USB_DIRECTION_IN ? 128 : 0) \
+			| ((p_type) << 5) \
+			| (p_recipient), \
+		.request = (p_request), \
+		{ .value = (p_value) }, \
+		.index = (p_index), \
+		.length = (p_length) \
+	}
+
+/** Prepare setup packet.
+ *
+ * @param name Variable name with the setup packet.
+ * @param p_direction Data transfer direction.
+ * @param p_type Request type (standard/class/vendor)
+ * @param p_recipient Recipient of the request.
+ * @param p_request Request.
+ * @param p_value_low wValue field of setup packet (low byte).
+ * @param p_value_high wValue field of setup packet (high byte).
+ * @param p_index wIndex field of setup packet.
+ * @param p_length Length of extra data.
+ */
+#define PREPARE_SETUP_PACKET_LOHI(name, p_direction, p_type, p_recipient, \
+    p_request, p_value_low, p_value_high, p_index, p_length) \
+	PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
+	    p_request, (p_value_low) | ((p_value_high) << 8), \
+	    p_index, p_length)
+
+/** Retrieve status of a USB device.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[in] recipient Recipient of the request.
+ * @param[in] recipient_index Index of @p recipient.
+ * @param[out] status Status (see figure 9-4 in USB 1.1 specification).
+ * @return Error code.
+ */
+int usb_drv_req_get_status(int hc_phone, usb_address_t address,
+    usb_request_recipient_t recipient, uint16_t recipient_index,
+    uint16_t *status)
+{
+	if (status == NULL) {
+		return EBADMEM;
+	}
+
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET(setup_packet,
+	    USB_DIRECTION_IN, USB_REQUEST_TYPE_STANDARD,
+	    recipient, USB_DEVREQ_GET_STATUS, 0, recipient_index, 2);
+
+	size_t transfered;
+	uint16_t tmp_status;
+	int rc = usb_drv_psync_control_read(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet), &tmp_status, 2, &transfered);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (transfered != 2) {
+		return ERANGE;
+	}
+
+	*status = tmp_status;
+
+	return EOK;
+}
+
+/** Clear or disable USB device feature.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[in] recipient Recipient of the request.
+ * @param[in] selector Feature selector.
+ * @param[in] index Index of @p recipient.
+ * @return Error code.
+ */
+int usb_drv_req_clear_feature(int hc_phone, usb_address_t address,
+    usb_request_recipient_t recipient,
+    uint16_t selector, uint16_t index)
+{
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET(setup_packet,
+	    USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
+	    recipient, USB_DEVREQ_CLEAR_FEATURE, selector, index, 0);
+
+	int rc = usb_drv_psync_control_write(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet), NULL, 0);
+
+	return rc;
+}
+
+/** Set or enable USB device feature.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[in] recipient Recipient of the request.
+ * @param[in] selector Feature selector.
+ * @param[in] index Index of @p recipient.
+ * @return Error code.
+ */
+int usb_drv_req_set_feature(int hc_phone, usb_address_t address,
+    usb_request_recipient_t recipient,
+    uint16_t selector, uint16_t index)
+{
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET(setup_packet,
+	    USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
+	    recipient, USB_DEVREQ_SET_FEATURE, selector, index, 0);
+
+	int rc = usb_drv_psync_control_write(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet), NULL, 0);
+
+	return rc;
+}
+
 /** Change address of connected device.
  *
@@ -44,7 +186,7 @@
  * @see usb_drv_bind_address
  *
- * @param phone Open phone to HC driver.
- * @param old_address Current address.
- * @param address Address to be set.
+ * @param[in] phone Open phone to HC driver.
+ * @param[in] old_address Current address.
+ * @param[in] address Address to be set.
  * @return Error code.
  */
@@ -52,18 +194,9 @@
     usb_address_t new_address)
 {
-	/* Prepare the target. */
-	usb_target_t target = {
-		.address = old_address,
-		.endpoint = 0
-	};
-
-	/* Prepare the setup packet. */
-	usb_device_request_setup_packet_t setup_packet = {
-		.request_type = 0,
-		.request = USB_DEVREQ_SET_ADDRESS,
-		.index = 0,
-		.length = 0,
-	};
-	setup_packet.value = new_address;
+	PREPARE_TARGET(target, old_address);
+
+	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_OUT,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_ADDRESS, new_address, 0, 0);
 
 	int rc = usb_drv_psync_control_write(phone, target,
@@ -73,8 +206,50 @@
 }
 
+/** Retrieve USB descriptor of connected USB device.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index.
+ * @param[out] buffer Buffer where to store the retrieved descriptor.
+ * @param[in] size Size of the @p buffer.
+ * @param[out] actual_size Number of bytes actually transferred.
+ * @return Error code.
+ */
+int usb_drv_req_get_descriptor(int hc_phone, usb_address_t address,
+    usb_request_type_t request_type,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void *buffer, size_t size, size_t *actual_size)
+{
+	if (buffer == NULL) {
+		return EBADMEM;
+	}
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	// FIXME: check that size is not too big
+
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_IN,
+	    request_type, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_GET_DESCRIPTOR, descriptor_index, descriptor_type,
+	    language, size);
+
+	int rc = usb_drv_psync_control_read(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet),
+	    buffer, size, actual_size);
+	
+	return rc;
+}
+
 /** Retrieve device descriptor of connected USB device.
  *
  * @param[in] phone Open phone to HC driver.
- * @param[in] address Device USB address.
+ * @param[in] address Device address.
  * @param[out] descriptor Storage for the device descriptor.
  * @return Error code.
@@ -87,29 +262,13 @@
 		return EBADMEM;
 	}
-
-	/* Prepare the target. */
-	usb_target_t target = {
-		.address = address,
-		.endpoint = 0
-	};
-
-	/* Prepare the setup packet. */
-	usb_device_request_setup_packet_t setup_packet = {
-		.request_type = 128,
-		.request = USB_DEVREQ_GET_DESCRIPTOR,
-		.index = 0,
-		.length = sizeof(usb_standard_device_descriptor_t)
-	};
-	setup_packet.value_high = USB_DESCTYPE_DEVICE;
-	setup_packet.value_low = 0;
-
-	/* Prepare local descriptor. */
+	
 	size_t actually_transferred = 0;
 	usb_standard_device_descriptor_t descriptor_tmp;
-
-	/* Perform the control read transaction. */
-	int rc = usb_drv_psync_control_read(phone, target,
-	    &setup_packet, sizeof(setup_packet),
-	    &descriptor_tmp, sizeof(descriptor_tmp), &actually_transferred);
+	int rc = usb_drv_req_get_descriptor(phone, address,
+	    USB_REQUEST_TYPE_STANDARD,
+	    USB_DESCTYPE_DEVICE, 0,
+	    0,
+	    &descriptor_tmp, sizeof(descriptor_tmp),
+	    &actually_transferred);
 
 	if (rc != EOK) {
@@ -137,5 +296,5 @@
  *
  * @param[in] phone Open phone to HC driver.
- * @param[in] address Device USB address.
+ * @param[in] address Device address.
  * @param[in] index Configuration descriptor index.
  * @param[out] descriptor Storage for the configuration descriptor.
@@ -150,29 +309,13 @@
 		return EBADMEM;
 	}
-
-	/* Prepare the target. */
-	usb_target_t target = {
-		.address = address,
-		.endpoint = 0
-	};
-
-	/* Prepare the setup packet. */
-	usb_device_request_setup_packet_t setup_packet = {
-		.request_type = 128,
-		.request = USB_DEVREQ_GET_DESCRIPTOR,
-		.index = 0,
-		.length = sizeof(usb_standard_configuration_descriptor_t)
-	};
-	setup_packet.value_high = USB_DESCTYPE_CONFIGURATION;
-	setup_packet.value_low = index;
-
-	/* Prepare local descriptor. */
+	
 	size_t actually_transferred = 0;
 	usb_standard_configuration_descriptor_t descriptor_tmp;
-
-	/* Perform the control read transaction. */
-	int rc = usb_drv_psync_control_read(phone, target,
-	    &setup_packet, sizeof(setup_packet),
-	    &descriptor_tmp, sizeof(descriptor_tmp), &actually_transferred);
+	int rc = usb_drv_req_get_descriptor(phone, address,
+	    USB_REQUEST_TYPE_STANDARD,
+	    USB_DESCTYPE_CONFIGURATION, 0,
+	    0,
+	    &descriptor_tmp, sizeof(descriptor_tmp),
+	    &actually_transferred);
 
 	if (rc != EOK) {
@@ -195,8 +338,8 @@
  *
  * @warning The @p buffer might be touched (i.e. its contents changed)
- * even when error occurres.
+ * even when error occurs.
  *
  * @param[in] phone Open phone to HC driver.
- * @param[in] address Device USB address.
+ * @param[in] address Device address.
  * @param[in] index Configuration descriptor index.
  * @param[out] buffer Buffer for the whole configuration descriptor.
@@ -210,32 +353,169 @@
     void *buffer, size_t buffer_size, size_t *actual_buffer_size)
 {
-	if (buffer == NULL) {
+	int rc = usb_drv_req_get_descriptor(phone, address,
+	    USB_REQUEST_TYPE_STANDARD,
+	    USB_DESCTYPE_CONFIGURATION, 0,
+	    0,
+	    buffer, buffer_size,
+	    actual_buffer_size);
+
+	return rc;
+}
+
+/** Update existing descriptor of a USB device.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[in] descriptor_type Descriptor type (device/configuration/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index.
+ * @param[in] descriptor Actual descriptor data.
+ * @param[in] descriptor_size Descriptor size.
+ * @return Error code.
+ */
+int usb_drv_req_set_descriptor(int hc_phone, usb_address_t address,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void *descriptor, size_t descriptor_size)
+{
+	// FIXME: check that descriptor is not too big
+
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_DESCRIPTOR, descriptor_index, descriptor_type,
+	    language, descriptor_size);
+
+	int rc = usb_drv_psync_control_write(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet),
+	    descriptor, descriptor_size);
+
+	return rc;
+}
+
+/** Determine current configuration value of USB device.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[out] configuration_value Current configuration value.
+ * @return Error code.
+ */
+int usb_drv_req_get_configuration(int hc_phone, usb_address_t address,
+    uint8_t *configuration_value)
+{
+	if (configuration_value == NULL) {
 		return EBADMEM;
 	}
 
-	/* Prepare the target. */
-	usb_target_t target = {
-		.address = address,
-		.endpoint = 0
-	};
-
-	/* Prepare the setup packet. */
-	usb_device_request_setup_packet_t setup_packet = {
-		.request_type = 128,
-		.request = USB_DEVREQ_GET_DESCRIPTOR,
-		.index = 0,
-		.length = buffer_size
-	};
-	setup_packet.value_high = USB_DESCTYPE_CONFIGURATION;
-	setup_packet.value_low = index;
-
-	/* Perform the control read transaction. */
-	int rc = usb_drv_psync_control_read(phone, target,
-	    &setup_packet, sizeof(setup_packet),
-	    buffer, buffer_size, actual_buffer_size);
-
-	return rc;
-}
-
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_GET_CONFIGURATION, 0, 0, 1);
+
+	uint8_t value;
+	size_t transfered;
+	int rc = usb_drv_psync_control_read(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet), &value, 1, &transfered);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (transfered != 1) {
+		return ERANGE;
+	}
+
+	*configuration_value = value;
+
+	return EOK;
+}
+
+/** Set configuration of USB device.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[in] configuration_value New configuration value.
+ * @return Error code.
+ */
+int usb_drv_req_set_configuration(int hc_phone, usb_address_t address,
+    uint8_t configuration_value)
+{
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_CONFIGURATION, configuration_value, 0,
+	    0, 0);
+
+	int rc = usb_drv_psync_control_write(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet), NULL, 0);
+
+	return rc;
+}
+
+/** Determine alternate setting of USB device interface.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[in] interface_index Interface index.
+ * @param[out] alternate_setting Value of alternate setting.
+ * @return Error code.
+ */
+int usb_drv_req_get_interface(int hc_phone, usb_address_t address,
+    uint16_t interface_index, uint8_t *alternate_setting)
+{
+	if (alternate_setting == NULL) {
+		return EBADMEM;
+	}
+
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DEVREQ_GET_INTERFACE, 0, interface_index, 1);
+
+	uint8_t alternate;
+	size_t transfered;
+	int rc = usb_drv_psync_control_read(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet), &alternate, 1, &transfered);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (transfered != 1) {
+		return ERANGE;
+	}
+
+	*alternate_setting = alternate;
+
+	return EOK;
+}
+
+/** Select an alternate setting of USB device interface.
+ *
+ * @param[in] hc_phone Open phone to HC driver.
+ * @param[in] address Device address.
+ * @param[in] interface_index Interface index.
+ * @param[in] alternate_setting Value of alternate setting.
+ * @return Error code.
+ */
+int usb_drv_req_set_interface(int hc_phone, usb_address_t address,
+    uint16_t interface_index, uint8_t alternate_setting)
+{
+	PREPARE_TARGET(target, address);
+
+	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DEVREQ_SET_INTERFACE, alternate_setting, 0,
+	    0, 0);
+
+	int rc = usb_drv_psync_control_write(hc_phone, target,
+	    &setup_packet, sizeof(setup_packet), NULL, 0);
+
+	return rc;
+}
 
 /**
