Index: uspace/lib/usbvirt/src/ctrlpipe.c
===================================================================
--- uspace/lib/usbvirt/src/ctrlpipe.c	(revision 75732daeac84e2935c03d316ed5cb327455ac6a3)
+++ uspace/lib/usbvirt/src/ctrlpipe.c	(revision 7feeb848f2e12de48c167eded31acbb40ded0caf)
@@ -37,32 +37,44 @@
 #include "private.h"
 
-#define REQUEST_TYPE_STANDARD 0 
-#define REQUEST_TYPE_CLASS 1
+/** Compares handler type with request packet type.
+ *
+ * @param handler Handler.
+ * @param request_packet Request packet.
+ * @return Whether handler can serve this packet.
+ */
+static bool is_suitable_handler(usbvirt_control_transfer_handler_t *handler,
+    usb_device_request_setup_packet_t *request_packet)
+{
+	return (
+	    (handler->request_type == request_packet->request_type)
+	    && (handler->request == request_packet->request));
 
-#define GET_MIDBITS_MASK(size, shift) \
-	(((1 << size) - 1) << shift)
-#define GET_MIDBITS(value, size, shift) \
-	((value & GET_MIDBITS_MASK(size, shift)) >> shift)
+}
+
+/** Find suitable transfer handler for given request packet.
+ *
+ * @param handlers Array of available handlers.
+ * @param request_packet Request SETUP packet.
+ * @return Handler or NULL.
+ */
+static usbvirt_control_transfer_handler_t *find_handler(
+    usbvirt_control_transfer_handler_t *handlers,
+    usb_device_request_setup_packet_t *request_packet)
+{
+	if (handlers == NULL) {
+		return NULL;
+	}
+
+	while (handlers->callback != NULL) {
+		if (is_suitable_handler(handlers, request_packet)) {
+			return handlers;
+		}
+		handlers++;
+	}
+
+	return NULL;
+}
 
 
-static const char *str_request_type(int type)
-{
-	switch (type) {
-		case REQUEST_TYPE_STANDARD:
-			return "standard";
-		case REQUEST_TYPE_CLASS:
-			return "class";
-		default:
-			return "unknown";
-	}
-}
-
-/** Tell request type.
- * By type is meant either standard, class, vendor or other.
- */
-static int request_get_type(uint8_t request_type)
-{
-	return GET_MIDBITS(request_type, 2, 5);
-}
 
 /** Handle communication over control pipe zero.
@@ -77,28 +89,39 @@
 	}
 	
-	usb_device_request_setup_packet_t *request = (usb_device_request_setup_packet_t *) transfer->request;
-	uint8_t *remaining_data = transfer->data;
+	usb_device_request_setup_packet_t *request
+	    = (usb_device_request_setup_packet_t *) transfer->request;
+	printf("Request: %d,%d\n", request->request_type, request->request);
 	
-	int type = request_get_type(request->request_type);
-	
-	int rc = EOK;
-	
-	device->lib_debug(device, 2, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
-	    "request type: %s", str_request_type(type));
-	
-	switch (type) {
-		case REQUEST_TYPE_STANDARD:
-			rc = handle_std_request(device, request, remaining_data);
-			break;
-		case REQUEST_TYPE_CLASS:
-			if (DEVICE_HAS_OP(device, on_class_device_request)) {
-				rc = device->ops->on_class_device_request(device,
-				    request, remaining_data);
-			}
-			break;
-		default:
-			break;
+	/*
+	 * First, see whether user provided its own callback.
+	 */
+	int rc = EFORWARD;
+	if (device->ops) {
+		usbvirt_control_transfer_handler_t *user_handler
+		    = find_handler(device->ops->control_transfer_handlers,
+		    request);
+		if (user_handler != NULL) {
+			rc = user_handler->callback(device, request,
+			    transfer->data);
+		}
+	}
+
+	/*
+	 * If there was no user callback or the callback returned EFORWARD,
+	 * we need to run a local handler.
+	 */
+	if (rc == EFORWARD) {
+		usbvirt_control_transfer_handler_t *lib_handler
+		    = find_handler(control_pipe_zero_local_handlers,
+		    request);
+		if (lib_handler != NULL) {
+			rc = lib_handler->callback(device, request,
+			    transfer->data);
+		}
 	}
 	
+	/*
+	 * Check for SET_ADDRESS finalization.
+	 */
 	if (device->new_address != -1) {
 		/*
Index: uspace/lib/usbvirt/src/private.h
===================================================================
--- uspace/lib/usbvirt/src/private.h	(revision 75732daeac84e2935c03d316ed5cb327455ac6a3)
+++ uspace/lib/usbvirt/src/private.h	(revision 7feeb848f2e12de48c167eded31acbb40ded0caf)
@@ -87,4 +87,6 @@
 }
 
+extern usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[];
+
 #endif
 /**
Index: uspace/lib/usbvirt/src/stdreq.c
===================================================================
--- uspace/lib/usbvirt/src/stdreq.c	(revision 75732daeac84e2935c03d316ed5cb327455ac6a3)
+++ uspace/lib/usbvirt/src/stdreq.c	(revision 7feeb848f2e12de48c167eded31acbb40ded0caf)
@@ -40,8 +40,4 @@
 #include "private.h"
 
-
-typedef int (*usbvirt_stdreq_handler_t)(usbvirt_device_t *,
-usb_device_request_setup_packet_t *, uint8_t *);
-
 /*
  * All sub handlers must return EFORWARD to inform the caller that
@@ -177,42 +173,29 @@
 }
 
-static usbvirt_stdreq_handler_t local_handlers[USB_DEVREQ_LAST_STD] = {
-	[USB_DEVREQ_GET_DESCRIPTOR] = handle_get_descriptor,
-	[USB_DEVREQ_SET_ADDRESS] = handle_set_address,
-	[USB_DEVREQ_SET_CONFIGURATION] = handle_set_configuration
+
+#define MAKE_BM_REQUEST(direction, recipient) \
+	USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \
+	    USBVIRT_REQUEST_TYPE_STANDARD, recipient)
+#define MAKE_BM_REQUEST_DEV(direction) \
+	MAKE_BM_REQUEST(direction, USBVIRT_REQUEST_RECIPIENT_DEVICE)
+
+usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[] = {
+	{
+		.request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN),
+		.request = USB_DEVREQ_GET_DESCRIPTOR,
+		.callback = handle_get_descriptor
+	},
+	{
+		.request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
+		.request = USB_DEVREQ_SET_ADDRESS,
+		.callback = handle_set_address
+	},
+	{
+		.request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT),
+		.request = USB_DEVREQ_SET_CONFIGURATION,
+		.callback = handle_set_configuration
+	},
+	USBVIRT_CONTROL_TRANSFER_HANDLER_LAST
 };
-
-/** Handle standard device request. */
-int handle_std_request(usbvirt_device_t *device,
-    usb_device_request_setup_packet_t *request_packet, uint8_t *data)
-{
-	int request = request_packet->request;
-
-	device->lib_debug(device, 3, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
-	    "handling standard request %d", request);
-
-	if (request >= USB_DEVREQ_LAST_STD) {
-		return ENOTSUP;
-	}
-	
-	int rc = EFORWARD;
-	if ((device->ops)
-	    && (device->ops->on_standard_request[request])) {
-		rc = device->ops->on_standard_request[request](device,
-		    request_packet, data);
-	}
-
-	if (rc == EFORWARD) {
-		if (local_handlers[request]) {
-			rc = local_handlers[request](device,
-			    request_packet, data);
-		} else {
-			rc = ENOTSUP;
-		}
-	}
-
-	assert(rc != EFORWARD);
-	return rc;
-}
 
 /**
