Index: uspace/lib/usbvirt/Makefile
===================================================================
--- uspace/lib/usbvirt/Makefile	(revision 23cb44b4470f76dd953fedf15da7a42f59fac14d)
+++ uspace/lib/usbvirt/Makefile	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
@@ -36,4 +36,5 @@
 	callback.c \
 	ctrlpipe.c \
+	debug.c \
 	main.c \
 	stdreq.c \
Index: uspace/lib/usbvirt/ctrlpipe.c
===================================================================
--- uspace/lib/usbvirt/ctrlpipe.c	(revision 23cb44b4470f76dd953fedf15da7a42f59fac14d)
+++ uspace/lib/usbvirt/ctrlpipe.c	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
@@ -45,5 +45,16 @@
 	((value & GET_MIDBITS_MASK(size, shift)) >> shift)
 
-usb_address_t dev_new_address = -1;
+
+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.
@@ -59,4 +70,7 @@
 int control_pipe(usbvirt_device_t *device, usbvirt_control_transfer_t *transfer)
 {
+	device->lib_debug(device, 1, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
+	    "op on control pipe zero (request_size=%u)", transfer->request_size);
+	
 	if (transfer->request_size < sizeof(usb_device_request_setup_packet_t)) {
 		return ENOMEM;
@@ -69,4 +83,7 @@
 	
 	int rc = EOK;
+	
+	device->lib_debug(device, 2, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
+	    "request type: %s", str_request_type(type));
 	
 	switch (type) {
@@ -97,4 +114,8 @@
 		
 		device->new_address = -1;
+		
+		device->lib_debug(device, 2, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
+		    "device address changed to %d (state %s)",
+		    device->address, str_device_state(device->state));
 	}
 	
Index: uspace/lib/usbvirt/debug.c
===================================================================
--- uspace/lib/usbvirt/debug.c	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
+++ uspace/lib/usbvirt/debug.c	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
@@ -0,0 +1,104 @@
+/*
+ * 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 Debugging support.
+ */
+#include <stdio.h>
+#include <bool.h>
+
+#include "device.h"
+#include "private.h"
+
+
+static void debug_print(int level, uint8_t tag,
+    int current_level, uint8_t enabled_tags,
+    const char *format, va_list args)
+{
+	if (level > current_level) {
+		return;
+	}
+	
+	if ((tag & enabled_tags) == 0) {
+		return;
+	}
+	
+	bool print_prefix = true;
+	
+	if ((format[0] == '%') && (format[1] == 'M')) {
+		format += 2;
+		print_prefix = false;
+	}
+	
+	if (print_prefix) {
+		printf("[vusb]: ", level);
+		while (--level > 0) {
+			printf(" ");
+		}
+	}
+	
+	vprintf(format, args);
+	
+	if (print_prefix) {
+		printf("\n");
+	}
+}
+
+
+void user_debug(usbvirt_device_t *device, int level, uint8_t tag,
+    const char *format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	
+	debug_print(level, tag,
+	    device->debug_level, device->debug_enabled_tags,
+	    format, args);
+	
+	va_end(args);
+}
+
+void lib_debug(usbvirt_device_t *device, int level, uint8_t tag,
+    const char *format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	
+	debug_print(level, tag,
+	    device->lib_debug_level, device->lib_debug_enabled_tags,
+	    format, args);
+	
+	va_end(args);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/device.h
===================================================================
--- uspace/lib/usbvirt/device.h	(revision 23cb44b4470f76dd953fedf15da7a42f59fac14d)
+++ uspace/lib/usbvirt/device.h	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
@@ -145,4 +145,11 @@
 } usbvirt_control_transfer_t;
 
+typedef enum {
+	USBVIRT_DEBUGTAG_BASE = 1,
+	USBVIRT_DEBUGTAG_TRANSACTION = 2,
+	USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO = 4,
+	USBVIRT_DEBUGTAG_ALL = 255
+} usbvirt_debug_tags_t;
+
 /** Virtual USB device. */
 struct usbvirt_device {
@@ -186,4 +193,28 @@
 	/** State information on control-transfer endpoints. */
 	usbvirt_control_transfer_t current_control_transfers[USB11_ENDPOINT_MAX];
+	
+	/* User debugging. */
+	
+	/** Debug print. */
+	void (*debug)(usbvirt_device_t *dev, int level, uint8_t tag,
+	    const char *format, ...);
+	
+	/** Current debug level. */
+	int debug_level;
+	
+	/** Bitmap of currently enabled tags. */
+	uint8_t debug_enabled_tags;
+	
+	/* Library debugging. */
+	
+	/** Debug print. */
+	void (*lib_debug)(usbvirt_device_t *dev, int level, uint8_t tag,
+	    const char *format, ...);
+	
+	/** Current debug level. */
+	int lib_debug_level;
+	
+	/** Bitmap of currently enabled tags. */
+	uint8_t lib_debug_enabled_tags;
 };
 
Index: uspace/lib/usbvirt/main.c
===================================================================
--- uspace/lib/usbvirt/main.c	(revision 23cb44b4470f76dd953fedf15da7a42f59fac14d)
+++ uspace/lib/usbvirt/main.c	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
@@ -124,4 +124,7 @@
 	dev->control_transfer_reply = control_transfer_reply;
 	
+	dev->debug = user_debug;
+	dev->lib_debug = lib_debug;
+	
 	dev->state = USBVIRT_STATE_DEFAULT;
 	dev->address = 0;
Index: uspace/lib/usbvirt/private.h
===================================================================
--- uspace/lib/usbvirt/private.h	(revision 23cb44b4470f76dd953fedf15da7a42f59fac14d)
+++ uspace/lib/usbvirt/private.h	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
@@ -66,4 +66,24 @@
     void *buffer, size_t size, size_t *data_size);
 
+
+void user_debug(usbvirt_device_t *device, int level, uint8_t tag,
+    const char *format, ...);
+void lib_debug(usbvirt_device_t *device, int level, uint8_t tag,
+    const char *format, ...);
+    
+static inline const char *str_device_state(usbvirt_device_state_t state)
+{
+	switch (state) {
+		case USBVIRT_STATE_DEFAULT:
+			return "default";
+		case USBVIRT_STATE_ADDRESS:
+			return "address";
+		case USBVIRT_STATE_CONFIGURED:
+			return "configured";
+		default:
+			return "unknown";
+	}
+}
+
 #endif
 /**
Index: uspace/lib/usbvirt/stdreq.c
===================================================================
--- uspace/lib/usbvirt/stdreq.c	(revision 23cb44b4470f76dd953fedf15da7a42f59fac14d)
+++ uspace/lib/usbvirt/stdreq.c	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
@@ -187,4 +187,7 @@
     usb_device_request_setup_packet_t *request, uint8_t *data)
 {
+	device->lib_debug(device, 3, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,
+	    "handling standard request %d", request->request);
+	
 	HANDLE_REQUEST(request, data, USB_DEVREQ_GET_DESCRIPTOR,
 	    device, on_get_descriptor,
Index: uspace/lib/usbvirt/transaction.c
===================================================================
--- uspace/lib/usbvirt/transaction.c	(revision 23cb44b4470f76dd953fedf15da7a42f59fac14d)
+++ uspace/lib/usbvirt/transaction.c	(revision af894a21f770d0fbb50043118dbc9445ae68f6c3)
@@ -67,4 +67,7 @@
     void *buffer, size_t size)
 {
+	device->lib_debug(device, 1, USBVIRT_DEBUGTAG_TRANSACTION,
+	    "setup transaction: endpoint=%d, size=%u", endpoint, size);
+	
 	usbvirt_control_transfer_t *transfer = &device->current_control_transfers[endpoint];
 	
@@ -97,4 +100,7 @@
     void *buffer, size_t size)
 {
+	device->lib_debug(device, 1, USBVIRT_DEBUGTAG_TRANSACTION,
+	    "out transaction: endpoint=%d, size=%u", endpoint, size);
+	
 	/*
 	 * First check whether it is a transaction over control pipe.
@@ -151,4 +157,7 @@
     void *buffer, size_t size, size_t *data_size)
 {
+	device->lib_debug(device, 1, USBVIRT_DEBUGTAG_TRANSACTION,
+	    "in transaction: endpoint=%d, size=%u", endpoint, size);
+	
 	/*
 	 * First check whether it is a transaction over control pipe.
