Index: uspace/lib/usbvirt/Makefile
===================================================================
--- uspace/lib/usbvirt/Makefile	(revision b8100da862d7faddeef79335833e685b1bc3b497)
+++ uspace/lib/usbvirt/Makefile	(revision 0e419571bdba43a9888b077d1994f873314353d3)
@@ -36,5 +36,6 @@
 	ctrlpipe.c \
 	incoming.c \
-	main.c
+	main.c \
+	stdreq.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usbvirt/ctrlpipe.c
===================================================================
--- uspace/lib/usbvirt/ctrlpipe.c	(revision b8100da862d7faddeef79335833e685b1bc3b497)
+++ uspace/lib/usbvirt/ctrlpipe.c	(revision 0e419571bdba43a9888b077d1994f873314353d3)
@@ -37,7 +37,71 @@
 #include "private.h"
 
+#define REQUEST_TYPE_STANDARD 0 
+#define REQUEST_TYPE_CLASS 1
+
+#define GET_MIDBITS_MASK(size, shift) \
+	(((1 << size) - 1) << shift)
+#define GET_MIDBITS(value, size, shift) \
+	((value & GET_MIDBITS_MASK(size, shift)) >> shift)
+
+static usb_direction_t request_get_direction(uint8_t request_type)
+{
+	int bit7 = GET_MIDBITS(request_type, 1, 7);
+	return bit7 ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+}
+
+static int request_get_type(uint8_t request_type)
+{
+	return GET_MIDBITS(request_type, 2, 5);
+}
+
+static int request_get_recipient(uint8_t request_type)
+{
+	return GET_MIDBITS(request_type, 5, 0);
+}
+
+
+typedef struct {
+	uint8_t request_type;
+	uint8_t request;
+	uint16_t value;
+	uint16_t index;
+	uint16_t length;
+} __attribute__ ((packed)) devreq_setup_packet_t;
+
 int control_pipe(void *buffer, size_t size)
 {
-	// TODO
+	if (size < sizeof(devreq_setup_packet_t)) {
+		return ENOMEM;
+	}
+	
+	devreq_setup_packet_t *request = (devreq_setup_packet_t *) buffer;
+	uint8_t *remaining_data = ((uint8_t *) request) + sizeof(devreq_setup_packet_t);
+	
+	usb_direction_t direction = request_get_direction(request->request_type);
+	int type = request_get_type(request->request_type);
+	int recipient = request_get_recipient(request->request_type);
+	
+	
+	switch (type) {
+		case REQUEST_TYPE_STANDARD:
+			return handle_std_request(direction, recipient,
+			    request->request, request->value,
+			    request->index, request->length,
+			    remaining_data);
+			break;
+		case REQUEST_TYPE_CLASS:
+			if (DEVICE_HAS_OP(device, on_devreq_class)) {
+				return device->ops->on_devreq_class(device,
+				    direction, recipient,
+				    request->request, request->value,
+				    request->index, request->length,
+				    remaining_data);
+			}
+			break;
+		default:
+			break;
+	}
+	
 	return EOK;
 }
Index: uspace/lib/usbvirt/device.h
===================================================================
--- uspace/lib/usbvirt/device.h	(revision b8100da862d7faddeef79335833e685b1bc3b497)
+++ uspace/lib/usbvirt/device.h	(revision 0e419571bdba43a9888b077d1994f873314353d3)
@@ -37,4 +37,5 @@
 
 #include <usb/hcd.h>
+#include <usb/device.h>
 #include <usb/devreq.h>
 
@@ -43,5 +44,6 @@
 typedef int (*usbvirt_on_devreq_t)(struct usbvirt_device *dev,
     usb_direction_t, int recipient,
-    usb_stddevreq_t, int value, int index, int length);
+    uint8_t request, uint16_t value, uint16_t index, uint16_t length,
+    uint8_t *remaining_data);
 
 typedef struct {
@@ -64,4 +66,17 @@
 	    usb_endpoint_t endpoint, void *buffer, size_t size);
 	
+	
+	
+	/* Device attributes. */
+	
+	/** Standard device descriptor.
+	 * If this descriptor is set (i.e. not NULL), the framework
+	 * automatically handles call for its retrieval.
+	 */
+	usb_standard_device_descriptor_t *standard_descriptor;
+	
+	
+	/* Private attributes. */
+	
 	/** Phone to HC.
 	 * @warning Do not change, this is private variable.
Index: uspace/lib/usbvirt/private.h
===================================================================
--- uspace/lib/usbvirt/private.h	(revision b8100da862d7faddeef79335833e685b1bc3b497)
+++ uspace/lib/usbvirt/private.h	(revision 0e419571bdba43a9888b077d1994f873314353d3)
@@ -41,4 +41,10 @@
 extern usbvirt_device_t *device;
 
+#define DEVICE_HAS_OP(dev, op) \
+	( \
+		(  ((dev)->ops) != NULL  ) \
+		&& \
+		(  ((dev)->ops->op) != NULL  ) \
+	)
 
 int usbvirt_data_to_host(struct usbvirt_device *dev,
@@ -49,4 +55,8 @@
 int control_pipe(void *buffer, size_t size);
 
+int handle_std_request(usb_direction_t direction, int recipient,
+    uint16_t request, uint16_t value, uint16_t index, uint16_t length,
+    uint8_t *remaining_data);
+
 #endif
 /**
Index: uspace/lib/usbvirt/stdreq.c
===================================================================
--- uspace/lib/usbvirt/stdreq.c	(revision 0e419571bdba43a9888b077d1994f873314353d3)
+++ uspace/lib/usbvirt/stdreq.c	(revision 0e419571bdba43a9888b077d1994f873314353d3)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2010 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 libusbvirt usb
+ * @{
+ */
+/** @file
+ * @brief Preprocessing of standard device requests.
+ */
+#include <errno.h>
+#include <usb/devreq.h>
+
+#include "private.h"
+
+/*
+ * All sub handlers must return EFORWARD to inform the caller that
+ * they were not able to process the request (yes, it is abuse of
+ * this error code but such error code shall not collide with anything
+ * else in this context).
+ */
+ 
+static int handle_get_descriptor(uint8_t type, uint8_t index, uint16_t language,
+    uint16_t length)
+{
+	/* 
+	 * Standard device descriptor.
+	 */
+	if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
+		if (device->standard_descriptor) {
+			return device->send_data(device, 0,
+			    device->standard_descriptor,
+			    device->standard_descriptor->length);
+		} else {
+			return EFORWARD;
+		}
+	}
+	
+	return EFORWARD;
+}
+
+static int handle_set_address(uint16_t new_address,
+    uint16_t zero1, uint16_t zero2)
+{
+	if ((zero1 != 0) || (zero2 != 0)) {
+		return EINVAL;
+	}
+	
+	if (new_address > 127) {
+		return EINVAL;
+	}
+	
+	/*
+	 * TODO: inform the HC that device has new address assigned.
+	 */
+	return EOK;
+}
+
+int handle_std_request(usb_direction_t direction, int recipient,
+    uint16_t request, uint16_t value, uint16_t index, uint16_t length,
+    uint8_t *remaining_data)
+{
+	int rc;
+	
+	switch (request) {
+		case USB_DEVREQ_GET_DESCRIPTOR:
+			rc = handle_get_descriptor(value >> 8, (uint8_t) value,
+			    index, length);
+			break;
+		
+		case USB_DEVREQ_SET_ADDRESS:
+			rc = handle_set_address(value, index, length);
+			break;
+		
+		default:
+			rc = EFORWARD;
+			break;
+	}
+	
+	/*
+	 * We preprocessed all we could.
+	 * If it was not enough, pass the request to the actual driver.
+	 */
+	if (rc == EFORWARD) {
+		if (DEVICE_HAS_OP(device, on_devreq_std)) {
+			return device->ops->on_devreq_std(device, direction,
+			    recipient,
+			    request, value, index,
+			    length, remaining_data);
+		}
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
