Index: uspace/app/virtusbkbd/Makefile
===================================================================
--- uspace/app/virtusbkbd/Makefile	(revision cbc00a4d09a551c46a855d6f5470025ec817afee)
+++ uspace/app/virtusbkbd/Makefile	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
@@ -38,4 +38,5 @@
 	kbdconfig.c \
 	keys.c \
+	stdreq.c \
 	virtusbkbd.c
 
Index: uspace/app/virtusbkbd/stdreq.c
===================================================================
--- uspace/app/virtusbkbd/stdreq.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/app/virtusbkbd/stdreq.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
@@ -0,0 +1,80 @@
+/*
+ * 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 usb
+ * @{
+ */
+/**
+ * @file
+ * @brief Keyboard configuration.
+ */
+#include <errno.h>
+#include <usb/descriptor.h>
+#include "stdreq.h"
+#include "kbdconfig.h"
+
+static int on_get_descriptor(struct usbvirt_device *dev,
+    usb_device_request_setup_packet_t *request, uint8_t *data);
+
+usbvirt_standard_device_request_ops_t standard_request_ops = {
+	.on_get_status = NULL,
+	.on_clear_feature = NULL,
+	.on_set_feature = NULL,
+	.on_set_address = NULL,
+	.on_get_descriptor = on_get_descriptor,
+	.on_set_descriptor = NULL,
+	.on_get_configuration = NULL,
+	.on_set_configuration = NULL,
+	.on_get_interface = NULL,
+	.on_set_interface = NULL,
+	.on_synch_frame = NULL
+};
+
+
+static int on_get_descriptor(struct usbvirt_device *dev,
+    usb_device_request_setup_packet_t *request, uint8_t *data)
+{
+	if (request->value_high == USB_DESCTYPE_HID_REPORT) {
+		/*
+		 * For simplicity, always return the same
+		 * report descriptor.
+		 */
+		int rc = dev->send_data(dev, 0,
+		    report_descriptor, report_descriptor_size);
+		
+		return rc;
+	}
+	
+	/* Let the framework handle all the rest. */
+	return EFORWARD;
+}
+
+
+
+/** @}
+ */
Index: uspace/app/virtusbkbd/stdreq.h
===================================================================
--- uspace/app/virtusbkbd/stdreq.h	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/app/virtusbkbd/stdreq.h	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
@@ -0,0 +1,45 @@
+/*
+ * 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 usb
+ * @{
+ */
+/** @file
+ * @brief Standard device request handlers.
+ */
+#ifndef VUK_STDREQ_H_
+#define VUK_STDREQ_H_
+
+#include <usbvirt/device.h>
+
+extern usbvirt_standard_device_request_ops_t standard_request_ops;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/virtusbkbd/virtusbkbd.c
===================================================================
--- uspace/app/virtusbkbd/virtusbkbd.c	(revision cbc00a4d09a551c46a855d6f5470025ec817afee)
+++ uspace/app/virtusbkbd/virtusbkbd.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
@@ -54,4 +54,5 @@
 #include "kbdconfig.h"
 #include "keys.h"
+#include "stdreq.h"
 
 #define LOOPS 5
@@ -76,5 +77,5 @@
 static int on_class_request(struct usbvirt_device *dev,
     usb_device_request_setup_packet_t *request, uint8_t *data)
-{
+{	
 	printf("%s: class request (%d)\n", NAME, (int) request->request);
 	
@@ -86,5 +87,6 @@
  */
 static usbvirt_device_ops_t keyboard_ops = {
-	.on_devreq_class = on_class_request,
+	.standard_request_ops = &standard_request_ops,
+	.on_class_device_request = on_class_request,
 	.on_data = on_incoming_data
 };
Index: uspace/lib/usb/descriptor.h
===================================================================
--- uspace/lib/usb/descriptor.h	(revision cbc00a4d09a551c46a855d6f5470025ec817afee)
+++ uspace/lib/usb/descriptor.h	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
@@ -45,5 +45,9 @@
 	USB_DESCTYPE_STRING = 3,
 	USB_DESCTYPE_INTERFACE = 4,
-	USB_DESCTYPE_ENDPOINT = 5
+	USB_DESCTYPE_ENDPOINT = 5,
+	USB_DESCTYPE_HID = 0x21,
+	USB_DESCTYPE_HID_REPORT = 0x22,
+	USB_DESCTYPE_HID_PHYSICAL = 0x23,
+	/* USB_DESCTYPE_ = */
 } usb_descriptor_type_t;
 
Index: uspace/lib/usbvirt/ctrlpipe.c
===================================================================
--- uspace/lib/usbvirt/ctrlpipe.c	(revision cbc00a4d09a551c46a855d6f5470025ec817afee)
+++ uspace/lib/usbvirt/ctrlpipe.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
@@ -68,6 +68,6 @@
 			break;
 		case REQUEST_TYPE_CLASS:
-			if (DEVICE_HAS_OP(device, on_devreq_class)) {
-				return device->ops->on_devreq_class(device,
+			if (DEVICE_HAS_OP(device, on_class_device_request)) {
+				return device->ops->on_class_device_request(device,
 				    request, remaining_data);
 			}
Index: uspace/lib/usbvirt/device.h
===================================================================
--- uspace/lib/usbvirt/device.h	(revision cbc00a4d09a551c46a855d6f5470025ec817afee)
+++ uspace/lib/usbvirt/device.h	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
@@ -46,13 +46,28 @@
 	uint8_t *data);
 
+/** Callbacks for standard device requests.
+ * When these functions are NULL or return EFORWARD, this
+ * framework will try to satisfy the request by itself.
+ */
+typedef struct {
+	usbvirt_on_device_request_t on_get_status;
+	usbvirt_on_device_request_t on_clear_feature;
+	usbvirt_on_device_request_t on_set_feature;
+	usbvirt_on_device_request_t on_set_address;
+	usbvirt_on_device_request_t on_get_descriptor;
+	usbvirt_on_device_request_t on_set_descriptor;
+	usbvirt_on_device_request_t on_get_configuration;
+	usbvirt_on_device_request_t on_set_configuration;
+	usbvirt_on_device_request_t on_get_interface;
+	usbvirt_on_device_request_t on_set_interface;
+	usbvirt_on_device_request_t on_synch_frame;
+} usbvirt_standard_device_request_ops_t;
+
 /** 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;
+	/** Callbacks for standard deivce requests. */
+	usbvirt_standard_device_request_ops_t *standard_request_ops;
 	/** Callback for class-specific USB request. */
-	usbvirt_on_device_request_t on_devreq_class;
+	usbvirt_on_device_request_t on_class_device_request;
 	/** Callback for all other incoming data. */
 	int (*on_data)(struct usbvirt_device *dev,
Index: uspace/lib/usbvirt/stdreq.c
===================================================================
--- uspace/lib/usbvirt/stdreq.c	(revision cbc00a4d09a551c46a855d6f5470025ec817afee)
+++ uspace/lib/usbvirt/stdreq.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
@@ -123,37 +123,34 @@
 }
 
+#define HANDLE_REQUEST(request, data, type, dev, user_callback, default_handler) \
+	do { \
+		if ((request)->request == (type)) { \
+			int _rc = EFORWARD; \
+			if (((dev)->ops) && ((dev)->ops->standard_request_ops) \
+			    && ((dev)->ops->standard_request_ops->user_callback)) { \
+				_rc = (dev)->ops->standard_request_ops->\
+				    user_callback(dev, request, data); \
+			} \
+			if (_rc == EFORWARD) { \
+				default_handler; \
+			} \
+			return _rc; \
+		} \
+	} while (false)
+
+
 int handle_std_request(usb_device_request_setup_packet_t *request, uint8_t *data)
 {
-	int rc;
+	HANDLE_REQUEST(request, data, USB_DEVREQ_GET_DESCRIPTOR,
+	    device, on_get_descriptor,
+	    handle_get_descriptor(request->value_low, request->value_high,
+	        request->index, request->length));
 	
-	switch (request->request) {
-		case USB_DEVREQ_GET_DESCRIPTOR:
-			rc = handle_get_descriptor(
-			    request->value_low, request->value_high,
-			    request->index, request->length);
-			break;
-		
-		case USB_DEVREQ_SET_ADDRESS:
-			rc = handle_set_address(request->value,
-			    request->index, request->length);
-			break;
-		
-		default:
-			rc = EFORWARD;
-			break;
-	}
+	HANDLE_REQUEST(request, data, USB_DEVREQ_SET_ADDRESS,
+	    device, on_set_address,
+	    handle_set_address(request->value,
+	        request->index, request->length));
 	
-	/*
-	 * 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,
-			    request, data);
-		}
-	}
-	
-	return EOK;
+	return ENOTSUP;
 }
 
