Index: uspace/app/virtusbkbd/kbdconfig.c
===================================================================
--- uspace/app/virtusbkbd/kbdconfig.c	(revision fd17ab54f5dcc26877b5231b7d2a83ee9e5dd5f9)
+++ uspace/app/virtusbkbd/kbdconfig.c	(revision 2c38125098827bdd626f5ecd8606e6b1b133dd24)
@@ -35,13 +35,15 @@
  */
 #include "kbdconfig.h"
+#include <usb/hcd.h>
+#include <usb/hid.h>
 #include <usb/hidut.h>
 #include <usb/classes.h>
 
 /** Standard device descriptor. */
-usb_standard_device_descriptor_t std_descriptor = {
+usb_standard_device_descriptor_t std_device_descriptor = {
 	.length = sizeof(usb_standard_device_descriptor_t),
-	.descriptor_type = 1,
+	.descriptor_type = USB_DESCTYPE_DEVICE,
 	.usb_spec_version = 0x110,
-	.device_class = USB_CLASS_HID,
+	.device_class = USB_CLASS_USE_INTERFACE,
 	.device_subclass = 0,
 	.device_protocol = 0,
@@ -49,5 +51,17 @@
 	.configuration_count = 1
 };
-size_t std_descriptor_size = sizeof(std_descriptor);
+
+/** Standard interface descriptor. */
+usb_standard_interface_descriptor_t std_interface_descriptor = {
+	.length = sizeof(usb_standard_interface_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_INTERFACE,
+	.interface_number = 0,
+	.alternate_setting = 0,
+	.endpoint_count = 1,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = 0,
+	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
+	.str_interface = 0
+};
 
 /** USB keyboard report descriptor.
@@ -105,5 +119,33 @@
 	.descriptor1_length = sizeof(report_descriptor)
 };
-size_t hid_descriptor_size = sizeof(hid_descriptor);
+
+/** Endpoint descriptor. */
+usb_standard_endpoint_descriptor_t endpoint_descriptor = {
+	.length = sizeof(usb_standard_endpoint_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_ENDPOINT,
+	.endpoint_address = 1 | 128,
+	.attributes = USB_TRANSFER_INTERRUPT,
+	.max_packet_size = 8,
+	.poll_interval = 10
+};
+
+/** Standard configuration descriptor. */
+usb_standard_configuration_descriptor_t std_configuration_descriptor = {
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
+	.total_length = 
+		sizeof(usb_standard_configuration_descriptor_t)
+		+ sizeof(std_interface_descriptor)
+		+ sizeof(hid_descriptor)
+		+ sizeof(endpoint_descriptor)
+		,
+	.interface_count = 1,
+	.configuration_number = 1,
+	.str_configuration = 0,
+	.attributes = 128, /* denotes bus-powered device */
+	.max_power = 50
+};
+
+
 
 
Index: uspace/app/virtusbkbd/kbdconfig.h
===================================================================
--- uspace/app/virtusbkbd/kbdconfig.h	(revision fd17ab54f5dcc26877b5231b7d2a83ee9e5dd5f9)
+++ uspace/app/virtusbkbd/kbdconfig.h	(revision 2c38125098827bdd626f5ecd8606e6b1b133dd24)
@@ -40,8 +40,15 @@
 #include "descriptor.h"
 
-extern usb_standard_device_descriptor_t std_descriptor;
-extern size_t std_descriptor_size;
+extern usb_standard_device_descriptor_t std_device_descriptor;
+
+extern usb_standard_configuration_descriptor_t std_configuration_descriptor;
+
+extern usb_standard_interface_descriptor_t std_interface_descriptor;
+
+extern usb_standard_endpoint_descriptor_t endpoint_descriptor;
+
+
 extern hid_descriptor_t hid_descriptor;
-extern size_t hid_descriptor_size;
+
 extern report_descriptor_data_t report_descriptor;
 extern size_t report_descriptor_size;
Index: uspace/app/virtusbkbd/virtusbkbd.c
===================================================================
--- uspace/app/virtusbkbd/virtusbkbd.c	(revision fd17ab54f5dcc26877b5231b7d2a83ee9e5dd5f9)
+++ uspace/app/virtusbkbd/virtusbkbd.c	(revision 2c38125098827bdd626f5ecd8606e6b1b133dd24)
@@ -89,4 +89,33 @@
 };
 
+usbvirt_device_configuration_extras_t extra_descriptors[] = {
+	{
+		.data = (uint8_t *) &std_interface_descriptor,
+		.length = sizeof(std_interface_descriptor)
+	},
+	{
+		.data = (uint8_t *) &hid_descriptor,
+		.length = sizeof(hid_descriptor)
+	},
+	{
+		.data = (uint8_t *) &endpoint_descriptor,
+		.length = sizeof(endpoint_descriptor)
+	}
+};
+
+/** Keyboard configuration. */
+usbvirt_device_configuration_t configuration = {
+	.descriptor = &std_configuration_descriptor,
+	.extra = extra_descriptors,
+	.extra_count = sizeof(extra_descriptors)/sizeof(extra_descriptors[0])
+};
+
+/** Keyboard standard descriptors. */
+usbvirt_descriptors_t descriptors = {
+	.device = &std_device_descriptor,
+	.configuration = &configuration,
+	.configuration_count = 1,
+};
+
 /** Keyboard device.
  * Rest of the items will be initialized later.
@@ -94,5 +123,5 @@
 static usbvirt_device_t keyboard_dev = {
 	.ops = &keyboard_ops,
-	.standard_descriptor = &std_descriptor,
+	.descriptors = &descriptors,
 	.device_id_ = USBVIRT_DEV_KEYBOARD_ID
 };
Index: uspace/lib/usbvirt/device.h
===================================================================
--- uspace/lib/usbvirt/device.h	(revision fd17ab54f5dcc26877b5231b7d2a83ee9e5dd5f9)
+++ uspace/lib/usbvirt/device.h	(revision 2c38125098827bdd626f5ecd8606e6b1b133dd24)
@@ -46,10 +46,49 @@
 	uint8_t *data);
 
+/** Device operations. */
 typedef struct {
+	/** Callback for standard USB request.
+	 * Called only when the request could not be handled by this
+	 * framework.
+	 */
 	usbvirt_on_device_request_t on_devreq_std;
+	/** Callback for class-specific USB request. */
 	usbvirt_on_device_request_t on_devreq_class;
+	/** Callback for all other incoming data. */
 	int (*on_data)(struct usbvirt_device *dev,
 	    usb_endpoint_t endpoint, void *buffer, size_t size);
 } usbvirt_device_ops_t;
+
+/** Extra configuration data for GET_CONFIGURATION request. */
+typedef struct {
+	/** Actual data. */
+	uint8_t *data;
+	/** Data length. */
+	size_t length;
+} usbvirt_device_configuration_extras_t;
+
+/** Single device configuration. */
+typedef struct {
+	/** Standard configuration descriptor. */
+	usb_standard_configuration_descriptor_t *descriptor;
+	/** Array of extra data. */
+	usbvirt_device_configuration_extras_t *extra;
+	/** Length of @c extra array. */
+	size_t extra_count;
+} usbvirt_device_configuration_t;
+
+/** Standard USB descriptors. */
+typedef struct {
+	/** Standard device descriptor.
+	 * There is always only one such descriptor for the device.
+	 */
+	usb_standard_device_descriptor_t *device;
+	
+	/** Configurations. */
+	usbvirt_device_configuration_t *configuration;
+	/** Number of configurations. */
+	size_t configuration_count;
+} usbvirt_descriptors_t;
+
 
 typedef struct usbvirt_device {
@@ -69,9 +108,6 @@
 	/* 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;
+	/** Standard descriptors. */
+	usbvirt_descriptors_t *descriptors;
 	
 	
Index: uspace/lib/usbvirt/stdreq.c
===================================================================
--- uspace/lib/usbvirt/stdreq.c	(revision fd17ab54f5dcc26877b5231b7d2a83ee9e5dd5f9)
+++ uspace/lib/usbvirt/stdreq.c	(revision 2c38125098827bdd626f5ecd8606e6b1b133dd24)
@@ -34,7 +34,11 @@
  */
 #include <errno.h>
+#include <stdlib.h>
+#include <mem.h>
 #include <usb/devreq.h>
 
 #include "private.h"
+
+
 
 /*
@@ -52,11 +56,49 @@
 	 */
 	if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
-		if (device->standard_descriptor) {
+		if (device->descriptors && device->descriptors->device) {
 			return device->send_data(device, 0,
-			    device->standard_descriptor,
-			    device->standard_descriptor->length);
+			    device->descriptors->device,
+			    device->descriptors->device->length);
 		} else {
 			return EFORWARD;
 		}
+	}
+	
+	/*
+	 * Configuration descriptor together with interface, endpoint and
+	 * class-specific descriptors.
+	 */
+	if (type == USB_DESCTYPE_CONFIGURATION) {
+		if (!device->descriptors) {
+			return EFORWARD;
+		}
+		if (index >= device->descriptors->configuration_count) {
+			return EFORWARD;
+		}
+		/* Copy the data. */
+		usbvirt_device_configuration_t *config = &device->descriptors
+		    ->configuration[index];
+		uint8_t *all_data = malloc(config->descriptor->total_length);
+		if (all_data == NULL) {
+			return ENOMEM;
+		}
+		
+		uint8_t *ptr = all_data;
+		memcpy(ptr, config->descriptor, config->descriptor->length);
+		ptr += config->descriptor->length;
+		size_t i;
+		for (i = 0; i < config->extra_count; i++) {
+			usbvirt_device_configuration_extras_t *extra
+			    = &config->extra[i];
+			memcpy(ptr, extra->data, extra->length);
+			ptr += extra->length;
+		}
+		
+		int rc = device->send_data(device, 0, all_data,
+		    config->descriptor->total_length);
+		
+		free(all_data);
+		
+		return rc;
 	}
 	
