Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ boot/Makefile.common	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -140,6 +140,8 @@
 	$(USPACE_PATH)/app/stats/stats \
 	$(USPACE_PATH)/app/sysinfo/sysinfo \
+	$(USPACE_PATH)/app/tasks/tasks \
 	$(USPACE_PATH)/app/top/top \
 	$(USPACE_PATH)/app/usbinfo/usbinfo \
+	$(USPACE_PATH)/app/virtusbkbd/vuk \
 	$(USPACE_PATH)/app/vuhid/vuh \
 	$(USPACE_PATH)/app/websrv/websrv
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/Makefile	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -51,4 +51,5 @@
 	app/top \
 	app/usbinfo \
+	app/virtusbkbd \
 	app/vuhid \
 	app/netecho \
Index: uspace/app/virtusbkbd/Makefile
===================================================================
--- uspace/app/virtusbkbd/Makefile	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/Makefile	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+# acronym for virtual usb keyboard
+# (it is really annoying to write long names)
+BINARY = vuk
+
+LIBS = $(LIBUSBVIRT_PREFIX)/libusbvirt.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -I$(LIBUSBVIRT_PREFIX)/include -I$(LIBDRV_PREFIX)/include
+
+SOURCES = \
+	kbdconfig.c \
+	keys.c \
+	stdreq.c \
+	virtusbkbd.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/virtusbkbd/descriptor.h
===================================================================
--- uspace/app/virtusbkbd/descriptor.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/descriptor.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,51 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/** @file
+ * @brief USB keyboard descriptors.
+ */
+#ifndef VUK_DESCRIPTOR_H_
+#define VUK_DESCRIPTOR_H_
+
+typedef struct {
+	uint8_t length;
+	uint8_t type;
+	uint16_t hid_spec_release;
+	uint8_t country_code;
+	uint8_t descriptor_count;
+	uint8_t descriptor1_type;
+	uint16_t descriptor1_length;
+} __attribute__ ((packed)) hid_descriptor_t;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/virtusbkbd/items.h
===================================================================
--- uspace/app/virtusbkbd/items.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/items.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,113 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/** @file
+ * @brief HID Item related functions.
+ */
+#ifndef VUK_ITEM_H_
+#define VUK_ITEM_H_
+
+#include <sys/types.h>
+
+typedef uint8_t report_descriptor_data_t[];
+
+/* Item types. */
+#define ITEM_MAIN 0
+#define ITEM_GLOBAL 1
+#define ITEM_LOCAL 2
+
+
+
+/* Item tags. */
+
+/* Main item tags. */
+#define TAG_INPUT 8
+#define TAG_OUTPUT 9
+#define TAG_FEATURE 11
+#define TAG_COLLECTION 10
+#define TAG_END_COLLECTION 12
+
+/* Global item tags. */
+#define TAG_USAGE_PAGE 0
+#define TAG_LOGICAL_MINIMUM 1
+#define TAG_LOGICAL_MAXIMUM 2
+#define TAG_REPORT_SIZE 7
+#define TAG_REPORT_COUNT 9
+
+/* Local item tags. */
+#define TAG_USAGE 0
+#define TAG_USAGE_MINIMUM 1
+#define TAG_USAGE_MAXIMUM 2
+
+
+/* Bits for Input, Output and Feature items. */
+#define _IOF(value, shift) ((value) << (shift))
+#define IOF_DATA _IOF(0, 0)
+#define IOF_CONSTANT _IOF(1, 0)
+#define IOF_ARRAY _IOF(0, 1)
+#define IOF_VARIABLE _IOF(1, 1)
+#define IOF_ABSOLUTE _IOF(0, 2)
+#define IOF_RELATIVE _IOF(1, 2)
+/* ... */
+
+/* Collection types. */
+#define COLLECTION_PHYSICAL 0x00
+#define COLLECTION_APPLICATION 0x01
+
+
+/** Creates item prefix.
+ * @param size Item size.
+ * @param type Item type.
+ * @param tag Item tag.
+ */
+#define BUILD_ITEM_PREFIX(size, type, tag) \
+	((size) | ((type) << 2) | ((tag) << 4))
+
+/** Create no-data item.
+ * @param type Item type.
+ * @param tag Item tag.
+ */
+#define ITEM_CREATE0(type, tag) \
+	BUILD_ITEM_PREFIX(0, type, tag)
+
+/** Create item with 1-byte data.
+ * @param type Item type.
+ * @param tag Item tag.
+ * @param data Item data (single byte).
+ */
+#define ITEM_CREATE1(type, tag, data) \
+	BUILD_ITEM_PREFIX(1, type, tag), data
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/virtusbkbd/kbdconfig.c
===================================================================
--- uspace/app/virtusbkbd/kbdconfig.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/kbdconfig.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,155 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/**
+ * @file
+ * @brief Keyboard configuration.
+ */
+#include "kbdconfig.h"
+#include "keys.h"
+#include <usb/usb.h>
+#include <usb/classes/hid.h>
+#include <usb/classes/hidut.h>
+#include <usb/classes/classes.h>
+
+/** Standard device descriptor. */
+usb_standard_device_descriptor_t std_device_descriptor = {
+	.length = sizeof(usb_standard_device_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_DEVICE,
+	.usb_spec_version = 0x110,
+	.device_class = USB_CLASS_USE_INTERFACE,
+	.device_subclass = 0,
+	.device_protocol = 0,
+	.max_packet_size = 64,
+	.configuration_count = 1
+};
+
+/** 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 = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
+	.str_interface = 0
+};
+
+/** USB keyboard report descriptor.
+ * Copied from USB HID 1.11 (section E.6).
+ */
+report_descriptor_data_t report_descriptor = {
+	STD_USAGE_PAGE(USB_HIDUT_PAGE_GENERIC_DESKTOP),
+	USAGE1(USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD),
+	START_COLLECTION(COLLECTION_APPLICATION),
+		STD_USAGE_PAGE(USB_HIDUT_PAGE_KEYBOARD),
+		USAGE_MINIMUM1(224),
+		USAGE_MAXIMUM1(231),
+		LOGICAL_MINIMUM1(0),
+		LOGICAL_MAXIMUM1(1),
+		REPORT_SIZE1(1),
+		REPORT_COUNT1(8),
+		/* Modifiers */
+		INPUT(IOF_DATA | IOF_VARIABLE | IOF_ABSOLUTE),
+		REPORT_COUNT1(1),
+		REPORT_SIZE1(8),
+		/* Reserved */
+		INPUT(IOF_CONSTANT),
+		REPORT_COUNT1(5),
+		REPORT_SIZE1(1),
+		STD_USAGE_PAGE(USB_HIDUT_PAGE_LED),
+		USAGE_MINIMUM1(1),
+		USAGE_MAXIMUM1(5),
+		/* LED states */
+		OUTPUT(IOF_DATA | IOF_VARIABLE | IOF_ABSOLUTE),
+		REPORT_COUNT1(1),
+		REPORT_SIZE1(3),
+		/* LED states padding */
+		OUTPUT(IOF_CONSTANT),
+		REPORT_COUNT1(KB_MAX_KEYS_AT_ONCE),
+		REPORT_SIZE1(8),
+		LOGICAL_MINIMUM1(0),
+		LOGICAL_MAXIMUM1(101),
+		STD_USAGE_PAGE(USB_HIDUT_PAGE_KEYBOARD),
+		USAGE_MINIMUM1(0),
+		USAGE_MAXIMUM1(101),
+		/* Key array */
+		INPUT(IOF_DATA | IOF_ARRAY),
+	END_COLLECTION()
+};
+size_t report_descriptor_size = sizeof(report_descriptor);
+
+/** HID descriptor. */
+hid_descriptor_t hid_descriptor = {
+	.length = sizeof(hid_descriptor_t),
+	.type = 0x21, // HID descriptor
+	.hid_spec_release = 0x101,
+	.country_code = 0,
+	.descriptor_count = 1,
+	.descriptor1_type = 0x22, // Report descriptor
+	.descriptor1_length = sizeof(report_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 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/kbdconfig.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,60 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/** @file
+ * @brief USB keyboard configuration.
+ */
+#ifndef VUK_KBDCONFIG_H_
+#define VUK_KBDCONFIG_H_
+
+#include <usb/descriptor.h>
+#include "report.h"
+#include "descriptor.h"
+
+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 report_descriptor_data_t report_descriptor;
+extern size_t report_descriptor_size;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/virtusbkbd/keys.c
===================================================================
--- uspace/app/virtusbkbd/keys.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/keys.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,123 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/**
+ * @file
+ * @brief Keyboard keys related structures.
+ */
+#include "keys.h"
+
+/** Initializes keyboard status. */
+void kb_init(kb_status_t *status)
+{
+	status->modifiers = 0;
+	size_t i;
+	for (i = 0; i < KB_MAX_KEYS_AT_ONCE; i++) {
+		status->pressed_keys[i] = 0;
+	}
+}
+
+/** Change pressed modifiers. */
+void kb_change_modifier(kb_status_t *status, kb_key_action_t action,
+    kb_modifier_t modifier)
+{
+	if (action == KB_KEY_DOWN) {
+		status->modifiers = status->modifiers | modifier;
+	} else {
+		status->modifiers = status->modifiers & (~modifier);
+	}
+}
+
+/** Find index of given key in key code array.
+ * @retval (size_t)-1 Key not found.
+ */
+static size_t find_key_index(kb_key_code_t *keys, size_t size, kb_key_code_t key)
+{
+	size_t i;
+	for (i = 0; i < size; i++) {
+		if (keys[i] == key) {
+			return i;
+		}
+	}
+	return (size_t)-1;
+}
+
+/** Change pressed key. */
+void kb_change_key(kb_status_t *status, kb_key_action_t action,
+    kb_key_code_t key_code)
+{
+	size_t pos = find_key_index(status->pressed_keys, KB_MAX_KEYS_AT_ONCE,
+	    key_code);
+	if (action == KB_KEY_DOWN) {
+		if (pos != (size_t)-1) {
+			return;
+		}
+		/*
+		 * Find first free item in the array.
+		 */
+		size_t i;
+		for (i = 0; i < KB_MAX_KEYS_AT_ONCE; i++) {
+			if (status->pressed_keys[i] == 0) {
+				status->pressed_keys[i] = key_code;
+				return;
+			}
+		}
+		// TODO - handle buffer overflow
+	} else {
+		if (pos == (size_t)-1) {
+			return;
+		}
+		status->pressed_keys[pos] = 0;
+	}	
+}
+
+/** Process list of events. */
+void kb_process_events(kb_status_t *status,
+    kb_event_t *events, size_t count,
+    kb_on_status_change on_change)
+{
+	while (count-- > 0) {
+		if (events->normal_key) {
+			kb_change_key(status, events->action,
+			    events->key_change);
+		} else {
+			kb_change_modifier(status, events->action,
+			    events->modifier_change);
+		}
+		if (on_change) {
+			on_change(status);
+		}
+		events++;
+	}
+}
+
+/** @}
+ */
Index: uspace/app/virtusbkbd/keys.h
===================================================================
--- uspace/app/virtusbkbd/keys.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/keys.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,121 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/** @file
+ * @brief Keyboard keys related structures.
+ */
+#ifndef VUK_KEYS_H_
+#define VUK_KEYS_H_
+
+#include <sys/types.h>
+#include <bool.h>
+
+/** Maximum number of keys that can be pressed simultaneously. */
+#define KB_MAX_KEYS_AT_ONCE 6
+
+/** Key code type. */
+typedef uint8_t kb_key_code_t;
+
+#define USB_HIDUT_KBD_KEY(name, usage_id, l, lc, l1, l2) \
+	KB_KEY_##name = usage_id,
+/** USB key code. */
+typedef enum {
+	#include <usb/classes/hidutkbd.h>
+} key_code_t;
+
+/** Modifier type. */
+typedef uint8_t kb_modifier_t;
+#define _KB_MOD(shift) (1 << (shift))
+#define KB_MOD_LEFT_CTRL _KB_MOD(0)
+#define KB_MOD_LEFT_SHIFT _KB_MOD(1)
+#define KB_MOD_LEFT_ALT _KB_MOD(2)
+#define KB_MOD_LEFT_GUI _KB_MOD(3)
+#define KB_MOD_RIGHT_CTRL _KB_MOD(4)
+#define KB_MOD_RIGHT_SHIFT _KB_MOD(5)
+#define KB_MOD_RIGHT_ALT _KB_MOD(6)
+#define KB_MOD_RIGHT_GUI _KB_MOD(7)
+
+/** Base key action. */
+typedef enum {
+	KB_KEY_DOWN,
+	KB_KEY_UP
+} kb_key_action_t;
+
+/** Keyboard status. */
+typedef struct {
+	/** Bitmap of pressed modifiers. */
+	kb_modifier_t modifiers;
+	/** Array of currently pressed keys. */
+	kb_key_code_t pressed_keys[KB_MAX_KEYS_AT_ONCE];
+} kb_status_t;
+
+/** Callback type for status change. */
+typedef void (*kb_on_status_change)(kb_status_t *);
+
+
+void kb_init(kb_status_t *);
+void kb_change_modifier(kb_status_t *, kb_key_action_t, kb_modifier_t);
+void kb_change_key(kb_status_t *, kb_key_action_t, kb_key_code_t);
+
+/** Keyboard event.
+ * Use macros M_DOWN, M_UP, K_DOWN, K_UP, K_PRESS to generate list
+ * of them.
+ */
+typedef struct {
+	/** Key action. */
+	kb_key_action_t action;
+	/** Switch whether action is about modifier or normal key. */
+	bool normal_key;
+	/** Modifier change. */
+	kb_modifier_t modifier_change;
+	/** Normal key change. */
+	kb_key_code_t key_change;
+} kb_event_t;
+
+#define M_DOWN(mod) \
+	{ KB_KEY_DOWN, false, (mod), 0 }
+#define M_UP(mod) \
+	{ KB_KEY_UP, false, (mod), 0 }
+#define K_DOWN(key) \
+	{ KB_KEY_DOWN, true, 0, (key) }
+#define K_UP(key) \
+	{ KB_KEY_UP, true, 0, (key) }
+#define K_PRESS(key) \
+	K_DOWN(key), K_UP(key)
+
+
+void kb_process_events(kb_status_t *, kb_event_t *, size_t, kb_on_status_change);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/virtusbkbd/report.h
===================================================================
--- uspace/app/virtusbkbd/report.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/report.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,85 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/** @file
+ * @brief HID Report Descriptor.
+ */
+#ifndef VUK_REPORT_H_
+#define VUK_REPORT_H_
+
+#include "items.h"
+
+/** Use standard Usage Page. */
+#define STD_USAGE_PAGE(page) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_USAGE_PAGE, page)
+
+/** Usage with one byte usage ID. */
+#define USAGE1(usage_id) \
+	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE, usage_id)
+
+/** Start a collection. */
+#define START_COLLECTION(collection) \
+	ITEM_CREATE1(ITEM_MAIN, TAG_COLLECTION, collection)
+
+/** End a collection. */
+#define END_COLLECTION() \
+	ITEM_CREATE0(ITEM_MAIN, TAG_END_COLLECTION)
+
+
+#define USAGE_MINIMUM1(value) \
+	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE_MINIMUM, value)
+	
+#define USAGE_MAXIMUM1(value) \
+	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE_MAXIMUM, value)
+	
+#define LOGICAL_MINIMUM1(value) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_LOGICAL_MINIMUM, value)
+
+#define LOGICAL_MAXIMUM1(value) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_LOGICAL_MAXIMUM, value)
+
+#define REPORT_SIZE1(size) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_REPORT_SIZE, size)
+
+#define REPORT_COUNT1(count) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_REPORT_COUNT, count)
+	
+#define INPUT(modifiers) \
+	ITEM_CREATE1(ITEM_MAIN, TAG_INPUT, modifiers)
+
+#define OUTPUT(modifiers) \
+	ITEM_CREATE1(ITEM_MAIN, TAG_OUTPUT, modifiers)
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/virtusbkbd/stdreq.c
===================================================================
--- uspace/app/virtusbkbd/stdreq.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/stdreq.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,64 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/**
+ * @file
+ * @brief Keyboard configuration.
+ */
+#include <errno.h>
+#include <usb/descriptor.h>
+#include "stdreq.h"
+#include "kbdconfig.h"
+
+int req_get_descriptor(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size)
+{
+	if (setup_packet->value_high == USB_DESCTYPE_HID_REPORT) {
+		/*
+		 * For simplicity, always return the same
+		 * report descriptor.
+		 */
+		usbvirt_control_reply_helper(setup_packet,
+		    data, act_size,
+		    report_descriptor, report_descriptor_size);
+
+		return EOK;
+	}
+	
+	/* Let the framework handle all the rest. */
+	return EFORWARD;
+}
+
+
+
+/** @}
+ */
Index: uspace/app/virtusbkbd/stdreq.h
===================================================================
--- uspace/app/virtusbkbd/stdreq.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/stdreq.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,47 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/** @file
+ * @brief Standard device request handlers.
+ */
+#ifndef VUK_STDREQ_H_
+#define VUK_STDREQ_H_
+
+#include <usbvirt/device.h>
+
+int req_get_descriptor(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/virtusbkbd/virtusbkbd.c
===================================================================
--- uspace/app/virtusbkbd/virtusbkbd.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/app/virtusbkbd/virtusbkbd.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,267 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/**
+ * @file
+ * @brief Virtual USB keyboard.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <vfs/vfs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+#include <async.h>
+
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+#include <usb/classes/hid.h>
+#include <usb/debug.h>
+#include <usbvirt/device.h>
+
+#include "kbdconfig.h"
+#include "keys.h"
+#include "stdreq.h"
+
+/** Pause between individual key-presses in seconds. */
+#define KEY_PRESS_DELAY 2
+#define NAME "virt-usb-kbd"
+
+
+#define __QUOTEME(x) #x
+#define _QUOTEME(x) __QUOTEME(x)
+
+#define VERBOSE_EXEC(cmd, fmt, ...) \
+	(printf("%s: %s" fmt "\n", NAME, _QUOTEME(cmd), __VA_ARGS__), cmd(__VA_ARGS__))
+
+kb_status_t status;
+
+/** Compares current and last status of pressed keys.
+ *
+ * @warning Has side-efect - changes status_last field.
+ *
+ * @param status_now Status now.
+ * @param status_last Last status.
+ * @param len Size of status.
+ * @return Whether they are the same.
+ */
+static bool keypress_check_with_last_request(uint8_t *status_now,
+    uint8_t *status_last, size_t len)
+{
+	bool same = true;
+	size_t i;
+	for (i = 0; i < len; i++) {
+		if (status_now[i] != status_last[i]) {
+			status_last[i] = status_now[i];
+			same = false;
+		}
+	}
+	return same;
+}
+
+static int on_request_for_data(usbvirt_device_t *dev,
+    usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
+    void *buffer, size_t size, size_t *actual_size)
+{
+	static uint8_t last_data[2 + KB_MAX_KEYS_AT_ONCE];
+
+	if (size < 2 + KB_MAX_KEYS_AT_ONCE) {
+		return EINVAL;
+	}
+	
+	*actual_size = 2 + KB_MAX_KEYS_AT_ONCE;
+	
+	uint8_t data[2 + KB_MAX_KEYS_AT_ONCE];
+	data[0] = status.modifiers;
+	data[1] = 0;
+	
+	size_t i;
+	for (i = 0; i < KB_MAX_KEYS_AT_ONCE; i++) {
+		data[2 + i] = status.pressed_keys[i];
+	}
+	
+	if (keypress_check_with_last_request(data, last_data,
+	    2 + KB_MAX_KEYS_AT_ONCE)) {
+		return ENAK;
+	}
+
+	memcpy(buffer, &data, *actual_size);
+	
+	return EOK;
+}
+
+static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
+	{
+		.req_direction = USB_DIRECTION_IN,
+		.req_type = USB_REQUEST_TYPE_STANDARD,
+		.req_recipient = USB_REQUEST_RECIPIENT_INTERFACE,
+		.request = USB_DEVREQ_GET_DESCRIPTOR,
+		.name = "GetDescriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		.callback = NULL
+	}
+};
+
+/** Keyboard callbacks.
+ * We abuse the fact that static variables are zero-filled.
+ */
+static usbvirt_device_ops_t keyboard_ops = {
+	.control = endpoint_zero_handlers,
+	.data_in[1] = on_request_for_data
+};
+
+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.
+ */
+static usbvirt_device_t keyboard_dev = {
+	.ops = &keyboard_ops,
+	.descriptors = &descriptors,
+	.name = "keyboard"
+};
+
+
+static void fibril_sleep(size_t sec)
+{
+	while (sec-- > 0) {
+		async_usleep(1000*1000);
+	}
+}
+
+
+/** Callback when keyboard status changed.
+ *
+ * @param status Current keyboard status.
+ */
+static void on_keyboard_change(kb_status_t *status)
+{
+	printf("%s: Current keyboard status: %02hhx", NAME, status->modifiers);
+	size_t i;
+	for (i = 0; i < KB_MAX_KEYS_AT_ONCE; i++) {
+		printf(" 0x%02X", (int)status->pressed_keys[i]);
+	}
+	printf("\n");
+	
+	fibril_sleep(KEY_PRESS_DELAY);
+}
+
+/** Simulated keyboard events. */
+static kb_event_t keyboard_events[] = {
+	/* Switch to VT6 (Alt+F6) */
+	M_DOWN(KB_MOD_LEFT_ALT),
+	K_PRESS(KB_KEY_F6),
+	M_UP(KB_MOD_LEFT_ALT),
+	/* Type the word 'Hello' */
+	M_DOWN(KB_MOD_LEFT_SHIFT),
+	K_PRESS(KB_KEY_H),
+	M_UP(KB_MOD_LEFT_SHIFT),
+	K_PRESS(KB_KEY_E),
+	K_PRESS(KB_KEY_L),
+	K_PRESS(KB_KEY_L),
+	K_PRESS(KB_KEY_O)
+};
+static size_t keyboard_events_count =
+    sizeof(keyboard_events)/sizeof(keyboard_events[0]);
+
+
+
+int main(int argc, char * argv[])
+{
+	printf("Dump of report descriptor (%zu bytes):\n", report_descriptor_size);
+	size_t i;
+	for (i = 0; i < report_descriptor_size; i++) {
+		printf("  0x%02X", report_descriptor[i]);
+		if (((i > 0) && (((i+1) % 10) == 0))
+		    || (i + 1 == report_descriptor_size)) {
+			printf("\n");
+		}
+	}
+	
+	kb_init(&status);
+	
+	
+	int rc = usbvirt_device_plug(&keyboard_dev, "/virt/usbhc/hc");
+	if (rc != EOK) {
+		printf("%s: Unable to start communication with VHCD (%s).\n",
+		    NAME, str_error(rc));
+		return rc;
+	}
+	
+	printf("%s: Simulating keyboard events...\n", NAME);
+	fibril_sleep(10);
+	//while (1) {
+		kb_process_events(&status, keyboard_events, keyboard_events_count,
+			on_keyboard_change);
+	//}
+	
+	printf("%s: Terminating...\n", NAME);
+	
+	//usbvirt_disconnect(&keyboard_dev);
+	
+	return 0;
+}
+
+
+/** @}
+ */
Index: uspace/app/vuhid/device.c
===================================================================
--- uspace/app/vuhid/device.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/app/vuhid/device.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -77,14 +77,8 @@
 {
 	vuhid_interface_t *iface = arg;
-	vuhid_data_t *hid_data = iface->vuhid_data;
 
 	if (iface->live != NULL) {
 		iface->live(iface);
 	}
-
-	fibril_mutex_lock(&hid_data->iface_count_mutex);
-	hid_data->iface_died_count++;
-	fibril_condvar_broadcast(&hid_data->iface_count_cv);
-	fibril_mutex_unlock(&hid_data->iface_count_mutex);
 
 	return EOK;
@@ -116,11 +110,4 @@
 	if ((iface->in_data_size == 0) && (iface->out_data_size == 0)) {
 		return EEMPTY;
-	}
-
-	// FIXME - we shall set vuhid_data to NULL in the main() rather
-	// than to depend on individual interfaces
-	/* Already used interface. */
-	if (iface->vuhid_data != NULL) {
-		return EEXISTS;
 	}
 
@@ -265,5 +252,4 @@
 
 	/* Launch the "life" fibril. */
-	iface->vuhid_data = hid_data;
 	fid_t life_fibril = fibril_create(interface_life_fibril, iface);
 	if (life_fibril == 0) {
@@ -324,5 +310,4 @@
 	    += total_descr_size;
 
-	hid_data->iface_count++;
 	fibril_add_ready(life_fibril);
 
@@ -346,15 +331,4 @@
 }
 
-void wait_for_interfaces_death(usbvirt_device_t *dev)
-{
-	vuhid_data_t *hid_data = dev->device_data;
-
-	fibril_mutex_lock(&hid_data->iface_count_mutex);
-	while (hid_data->iface_died_count < hid_data->iface_count) {
-		fibril_condvar_wait(&hid_data->iface_count_cv,
-		    &hid_data->iface_count_mutex);
-	}
-	fibril_mutex_unlock(&hid_data->iface_count_mutex);
-}
 
 /** @}
Index: uspace/app/vuhid/hids/bootkbd.c
===================================================================
--- uspace/app/vuhid/hids/bootkbd.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/app/vuhid/hids/bootkbd.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -39,5 +39,5 @@
 #include <usb/classes/hidut.h>
 
-#include "../report.h"
+#include "../../virtusbkbd/report.h"
 
 uint8_t report_descriptor[] = {
@@ -169,7 +169,5 @@
 	.on_data_out = on_data_out,
 
-	.live = live,
-
-	.vuhid_data = NULL
+	.live = live
 };
 
Index: pace/app/vuhid/items.h
===================================================================
--- uspace/app/vuhid/items.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ 	(revision )
@@ -1,113 +1,0 @@
-/*
- * 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 usbvirtkbd
- * @{
- */
-/** @file
- * @brief HID Item related functions.
- */
-#ifndef VUK_ITEM_H_
-#define VUK_ITEM_H_
-
-#include <sys/types.h>
-
-typedef uint8_t report_descriptor_data_t[];
-
-/* Item types. */
-#define ITEM_MAIN 0
-#define ITEM_GLOBAL 1
-#define ITEM_LOCAL 2
-
-
-
-/* Item tags. */
-
-/* Main item tags. */
-#define TAG_INPUT 8
-#define TAG_OUTPUT 9
-#define TAG_FEATURE 11
-#define TAG_COLLECTION 10
-#define TAG_END_COLLECTION 12
-
-/* Global item tags. */
-#define TAG_USAGE_PAGE 0
-#define TAG_LOGICAL_MINIMUM 1
-#define TAG_LOGICAL_MAXIMUM 2
-#define TAG_REPORT_SIZE 7
-#define TAG_REPORT_COUNT 9
-
-/* Local item tags. */
-#define TAG_USAGE 0
-#define TAG_USAGE_MINIMUM 1
-#define TAG_USAGE_MAXIMUM 2
-
-
-/* Bits for Input, Output and Feature items. */
-#define _IOF(value, shift) ((value) << (shift))
-#define IOF_DATA _IOF(0, 0)
-#define IOF_CONSTANT _IOF(1, 0)
-#define IOF_ARRAY _IOF(0, 1)
-#define IOF_VARIABLE _IOF(1, 1)
-#define IOF_ABSOLUTE _IOF(0, 2)
-#define IOF_RELATIVE _IOF(1, 2)
-/* ... */
-
-/* Collection types. */
-#define COLLECTION_PHYSICAL 0x00
-#define COLLECTION_APPLICATION 0x01
-
-
-/** Creates item prefix.
- * @param size Item size.
- * @param type Item type.
- * @param tag Item tag.
- */
-#define BUILD_ITEM_PREFIX(size, type, tag) \
-	((size) | ((type) << 2) | ((tag) << 4))
-
-/** Create no-data item.
- * @param type Item type.
- * @param tag Item tag.
- */
-#define ITEM_CREATE0(type, tag) \
-	BUILD_ITEM_PREFIX(0, type, tag)
-
-/** Create item with 1-byte data.
- * @param type Item type.
- * @param tag Item tag.
- * @param data Item data (single byte).
- */
-#define ITEM_CREATE1(type, tag, data) \
-	BUILD_ITEM_PREFIX(1, type, tag), data
-
-
-#endif
-/**
- * @}
- */
Index: uspace/app/vuhid/main.c
===================================================================
--- uspace/app/vuhid/main.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/app/vuhid/main.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -132,11 +132,6 @@
 	.in_endpoint_first_free = 1,
 	.out_endpoints_mapping = { NULL },
-	.out_endpoint_first_free = 1,
-
-	.iface_count = 0,
-	.iface_died_count = 0
-	// mutex and CV must be initialized elsewhere
+	.out_endpoint_first_free = 1
 };
-
 
 /** Keyboard device.
@@ -156,7 +151,4 @@
 
 	usb_log_enable(USB_LOG_LEVEL_DEBUG2, "vusbhid");
-
-	fibril_mutex_initialize(&vuhid_data.iface_count_mutex);
-	fibril_condvar_initialize(&vuhid_data.iface_count_cv);
 
 	/* Determine which interfaces to initialize. */
@@ -190,10 +182,10 @@
 	printf("Connected to VHCD...\n");
 
-	wait_for_interfaces_death(&hid_dev);
+	while (true) {
+		async_usleep(10 * 1000 * 1000);
+	}
 	
 	printf("Terminating...\n");
 	
-	usbvirt_device_unplug(&hid_dev);
-
 	return 0;
 }
Index: pace/app/vuhid/report.h
===================================================================
--- uspace/app/vuhid/report.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * 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 usbvirtkbd
- * @{
- */
-/** @file
- * @brief HID Report Descriptor.
- */
-#ifndef VUK_REPORT_H_
-#define VUK_REPORT_H_
-
-#include "items.h"
-
-/** Use standard Usage Page. */
-#define STD_USAGE_PAGE(page) \
-	ITEM_CREATE1(ITEM_GLOBAL, TAG_USAGE_PAGE, page)
-
-/** Usage with one byte usage ID. */
-#define USAGE1(usage_id) \
-	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE, usage_id)
-
-/** Start a collection. */
-#define START_COLLECTION(collection) \
-	ITEM_CREATE1(ITEM_MAIN, TAG_COLLECTION, collection)
-
-/** End a collection. */
-#define END_COLLECTION() \
-	ITEM_CREATE0(ITEM_MAIN, TAG_END_COLLECTION)
-
-
-#define USAGE_MINIMUM1(value) \
-	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE_MINIMUM, value)
-	
-#define USAGE_MAXIMUM1(value) \
-	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE_MAXIMUM, value)
-	
-#define LOGICAL_MINIMUM1(value) \
-	ITEM_CREATE1(ITEM_GLOBAL, TAG_LOGICAL_MINIMUM, value)
-
-#define LOGICAL_MAXIMUM1(value) \
-	ITEM_CREATE1(ITEM_GLOBAL, TAG_LOGICAL_MAXIMUM, value)
-
-#define REPORT_SIZE1(size) \
-	ITEM_CREATE1(ITEM_GLOBAL, TAG_REPORT_SIZE, size)
-
-#define REPORT_COUNT1(count) \
-	ITEM_CREATE1(ITEM_GLOBAL, TAG_REPORT_COUNT, count)
-	
-#define INPUT(modifiers) \
-	ITEM_CREATE1(ITEM_MAIN, TAG_INPUT, modifiers)
-
-#define OUTPUT(modifiers) \
-	ITEM_CREATE1(ITEM_MAIN, TAG_OUTPUT, modifiers)
-
-
-#endif
-/**
- * @}
- */
Index: uspace/app/vuhid/virthid.h
===================================================================
--- uspace/app/vuhid/virthid.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/app/vuhid/virthid.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -38,5 +38,4 @@
 #include <usb/usb.h>
 #include <usbvirt/device.h>
-#include <fibril_synch.h>
 
 #define VUHID_ENDPOINT_MAX USB11_ENDPOINT_MAX
@@ -44,17 +43,4 @@
 
 typedef struct vuhid_interface vuhid_interface_t;
-
-typedef struct {
-	vuhid_interface_t *in_endpoints_mapping[VUHID_ENDPOINT_MAX];
-	size_t in_endpoint_first_free;
-	vuhid_interface_t *out_endpoints_mapping[VUHID_ENDPOINT_MAX];
-	size_t out_endpoint_first_free;
-	vuhid_interface_t *interface_mapping[VUHID_INTERFACE_MAX];
-
-	fibril_mutex_t iface_count_mutex;
-	fibril_condvar_t iface_count_cv;
-	size_t iface_count;
-	size_t iface_died_count;
-} vuhid_data_t;
 
 struct vuhid_interface {
@@ -77,7 +63,13 @@
 
 	void *interface_data;
+};
 
-	vuhid_data_t *vuhid_data;
-};
+typedef struct {
+	vuhid_interface_t *in_endpoints_mapping[VUHID_ENDPOINT_MAX];
+	size_t in_endpoint_first_free;
+	vuhid_interface_t *out_endpoints_mapping[VUHID_ENDPOINT_MAX];
+	size_t out_endpoint_first_free;
+	vuhid_interface_t *interface_mapping[VUHID_INTERFACE_MAX];
+} vuhid_data_t;
 
 typedef struct {
@@ -92,5 +84,4 @@
 
 int add_interface_by_id(vuhid_interface_t **, const char *, usbvirt_device_t *);
-void wait_for_interfaces_death(usbvirt_device_t *);
 
 #endif
Index: uspace/drv/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/usbhid/generic/hiddev.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/drv/usbhid/generic/hiddev.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -39,5 +39,4 @@
 #include <errno.h>
 #include <str_error.h>
-#include <bool.h>
 
 #include <usbhid_iface.h>
@@ -65,6 +64,4 @@
     size_t size, size_t *act_size, unsigned int flags);
 
-static int usb_generic_hid_client_connected(ddf_fun_t *fun);
-
 /*----------------------------------------------------------------------------*/
 
@@ -75,6 +72,5 @@
 
 static ddf_dev_ops_t usb_generic_hid_ops = {
-	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
-	.open = usb_generic_hid_client_connected
+	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface
 };
 
@@ -108,25 +104,10 @@
 	
 	/*! @todo This should probably be atomic. */
-	if (usb_hid_report_ready()) {
-		memcpy(buffer, hid_dev->input_report, 
-		    hid_dev->input_report_size);
-		*act_size = hid_dev->input_report_size;
-		usb_hid_report_received();
-	}
+	memcpy(buffer, hid_dev->input_report, hid_dev->input_report_size);
+	*act_size = hid_dev->input_report_size;
 	
 	// clear the buffer so that it will not be received twice
-	//memset(hid_dev->input_report, 0, hid_dev->input_report_size);
+	memset(hid_dev->input_report, 0, hid_dev->input_report_size);
 	
-	// note that we already received this report
-//	report_received = true;
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_generic_hid_client_connected(ddf_fun_t *fun)
-{
-	usb_hid_report_received();
 	return EOK;
 }
Index: uspace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/drv/usbhid/kbd/kbddev.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -255,6 +255,4 @@
 	
 	if (hid_dev == NULL || hid_dev->data == NULL) {
-		usb_log_debug("default_connection_handler: "
-		    "Missing parameter.\n");
 		async_answer_0(icallid, EINVAL);
 		return;
@@ -269,6 +267,4 @@
 
 		if (kbd_dev->console_phone != -1) {
-			usb_log_debug("default_connection_handler: "
-			    "console phone already set\n");
 			async_answer_0(icallid, ELIMIT);
 			return;
@@ -276,11 +272,8 @@
 
 		kbd_dev->console_phone = callback;
-		
-		usb_log_debug("default_connection_handler: OK\n");
 		async_answer_0(icallid, EOK);
 		return;
 	}
 	
-	usb_log_debug("default_connection_handler: Wrong function.\n");
 	async_answer_0(icallid, EINVAL);
 }
@@ -562,8 +555,8 @@
 			usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
 			    kbd_dev->keys[i]);
+			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
 			if (!usb_kbd_is_lock(key)) {
 				usb_kbd_repeat_start(kbd_dev, key);
 			}
-			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
 		} else {
 			// found, nothing happens
Index: uspace/drv/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/drv/usbhid/mouse/mousedev.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -43,8 +43,4 @@
 #include <str_error.h>
 #include <ipc/mouse.h>
-#include <io/console.h>
-
-#include <ipc/kbd.h>
-#include <io/keycode.h>
 
 #include "mousedev.h"
@@ -65,7 +61,5 @@
 
 const char *HID_MOUSE_FUN_NAME = "mouse";
-const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
 const char *HID_MOUSE_CLASS_NAME = "mouse";
-const char *HID_MOUSE_WHEEL_CLASS_NAME = "keyboard";
 
 /** Default idle rate for mouses. */
@@ -125,6 +119,4 @@
 	
 	if (hid_dev == NULL || hid_dev->data == NULL) {
-		usb_log_debug("default_connection_handler: Missing "
-		    "parameters.\n");
 		async_answer_0(icallid, EINVAL);
 		return;
@@ -135,19 +127,13 @@
 	usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
 	
-	int *phone = (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) 
-		     ? &mouse_dev->mouse_phone : &mouse_dev->wheel_phone;
-	
 	if (method == IPC_M_CONNECT_TO_ME) {
 		int callback = IPC_GET_ARG5(*icall);
 
-		if (*phone != -1) {
-			usb_log_debug("default_connection_handler: Console "
-			    "phone to mouse already set.\n");
+		if (mouse_dev->console_phone != -1) {
 			async_answer_0(icallid, ELIMIT);
-			//async_answer_0(icallid, EOK);
 			return;
 		}
 
-		*phone = callback;
+		mouse_dev->console_phone = callback;
 		usb_log_debug("Console phone to mouse set ok (%d).\n", callback);
 		async_answer_0(icallid, EOK);
@@ -155,5 +141,4 @@
 	}
 
-	usb_log_debug("default_connection_handler: Invalid function.\n");
 	async_answer_0(icallid, EINVAL);
 }
@@ -167,6 +152,5 @@
 		return NULL;
 	}
-	mouse->mouse_phone = -1;
-	mouse->wheel_phone = -1;
+	mouse->console_phone = -1;
 	
 	return mouse;
@@ -180,10 +164,6 @@
 	
 	// hangup phone to the console
-	if ((*mouse_dev)->mouse_phone >= 0) {
-		async_hangup((*mouse_dev)->mouse_phone);
-	}
-	
-	if ((*mouse_dev)->wheel_phone >= 0) {
-		async_hangup((*mouse_dev)->wheel_phone);
+	if ((*mouse_dev)->console_phone >= 0) {
+		async_hangup((*mouse_dev)->console_phone);
 	}
 	
@@ -194,36 +174,6 @@
 /*----------------------------------------------------------------------------*/
 
-static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
-{
-	console_event_t ev;
-	
-	ev.type = KEY_PRESS;
-	ev.key = (wheel > 0) ? KC_UP : (wheel < 0) ? KC_DOWN : 0;
-	ev.mods = 0;
-	ev.c = 0;
-
-	if (mouse_dev->wheel_phone < 0) {
-		usb_log_warning(
-		    "Connection to console not ready, key discarded.\n");
-		return;
-	}
-	
-	int count = (wheel < 0) ? -wheel : wheel;
-	int i;
-	
-	for (i = 0; i < count * 3; ++i) {
-		usb_log_debug2("Sending key %d to the console\n", ev.key);
-		async_msg_4(mouse_dev->wheel_phone, KBD_EVENT, ev.type, 
-		    ev.key, ev.mods, ev.c);
-		// send key release right away
-		async_msg_4(mouse_dev->wheel_phone, KBD_EVENT, KEY_RELEASE, 
-		    ev.key, ev.mods, ev.c);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev, uint8_t *buffer,
-    size_t buffer_size)
+static bool usb_mouse_process_boot_report(usb_hid_dev_t *hid_dev,
+    uint8_t *buffer, size_t buffer_size)
 {
 	usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
@@ -232,5 +182,5 @@
 	    usb_debug_str_buffer(buffer, buffer_size, 0));
 	
-	if (mouse_dev->mouse_phone < 0) {
+	if (mouse_dev->console_phone < 0) {
 		usb_log_error(NAME " No console phone.\n");
 		return false;	// ??
@@ -302,35 +252,7 @@
 	
 	if ((shift_x != 0) || (shift_y != 0)) {
-		async_req_2_0(mouse_dev->mouse_phone,
+		async_req_2_0(mouse_dev->console_phone,
 		    MEVENT_MOVE, shift_x, shift_y);
 	}
-	
-	/*
-	 * Wheel
-	 */
-	int wheel = 0;
-	
-	path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 
-	    USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
-
-	usb_hid_report_path_set_report_id(path, report_id);
-	
-	field = usb_hid_report_get_sibling(
-	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 
-	    USB_HID_REPORT_TYPE_INPUT);
-
-	if (field != NULL) {
-		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
-		    field->usage);
-		wheel = field->value;
-	}
-
-	usb_hid_report_path_free(path);
-	
-	// send arrow up for positive direction and arrow down for negative
-	// direction; three arrows for difference of 1
-	usb_mouse_send_wheel(mouse_dev, wheel);
-	
 	
 	/*
@@ -352,5 +274,5 @@
 		if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
 		    && field->value != 0) {
-			async_req_2_0(mouse_dev->mouse_phone,
+			async_req_2_0(mouse_dev->console_phone,
 			    MEVENT_BUTTON, field->usage, 1);
 			mouse_dev->buttons[field->usage - field->usage_minimum]
@@ -359,5 +281,5 @@
 		    mouse_dev->buttons[field->usage - field->usage_minimum] != 0
 		    && field->value == 0) {
-		       async_req_2_0(mouse_dev->mouse_phone,
+		       async_req_2_0(mouse_dev->console_phone,
 			   MEVENT_BUTTON, field->usage, 0);
 		       mouse_dev->buttons[field->usage - field->usage_minimum]
@@ -415,42 +337,4 @@
 	}
 	
-	/*
-	 * Special function for acting as keyboard (wheel)
-	 */
-	usb_log_debug("Creating DDF function %s...\n", 
-	              HID_MOUSE_WHEEL_FUN_NAME);
-	fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
-	    HID_MOUSE_WHEEL_FUN_NAME);
-	if (fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	/*
-	 * Store the initialized HID device and HID ops
-	 * to the DDF function.
-	 */
-	fun->ops = &hid_dev->ops;
-	fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
-	usb_log_debug("Adding DDF function to class %s...\n", 
-	    HID_MOUSE_WHEEL_CLASS_NAME);
-	rc = ddf_fun_add_to_class(fun, HID_MOUSE_WHEEL_CLASS_NAME);
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class %s: %s.\n",
-		    HID_MOUSE_WHEEL_CLASS_NAME, str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-	
 	return EOK;
 }
@@ -523,5 +407,5 @@
 	}
 	
-	return usb_mouse_process_report(hid_dev, buffer, buffer_size);
+	return usb_mouse_process_boot_report(hid_dev, buffer, buffer_size);
 }
 
Index: uspace/drv/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/drv/usbhid/mouse/mousedev.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -48,6 +48,5 @@
 	//suseconds_t poll_interval_us;
 	/** IPC phone to console (consumer). */
-	int mouse_phone;
-	int wheel_phone;
+	int console_phone;
 	
 	int32_t *buttons;
Index: uspace/drv/usbhid/subdrivers.c
===================================================================
--- uspace/drv/usbhid/subdrivers.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/drv/usbhid/subdrivers.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -36,16 +36,9 @@
 #include "subdrivers.h"
 #include "usb/classes/hidut.h"
-#include "usb/classes/hidpath.h"
 
 #include "lgtch-ultrax/lgtch-ultrax.h"
-#include "mouse/mousedev.h"
 
 static usb_hid_subdriver_usage_t path_kbd[] = {
 	{USB_HIDUT_PAGE_KEYBOARD, 0}, 
-	{0, 0}
-};
-
-static usb_hid_subdriver_usage_t path_mouse2[] = {
-	{USB_HIDUT_PAGE_GENERIC_DESKTOP, USB_HIDUT_USAGE_GENERIC_DESKTOP_X},
 	{0, 0}
 };
@@ -86,18 +79,4 @@
 		}
 	},
-	{
-		path_mouse2,
-		-1,
-		USB_HID_PATH_COMPARE_END 
-		| USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
-		-1,
-		-1,
-		{
-			.init = usb_mouse_init,
-			.deinit = usb_mouse_deinit,
-			.poll = usb_mouse_polling_callback,
-			.poll_end = NULL
-		}
-	},
 	{NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL}}
 };
Index: uspace/drv/usbhid/usbhid.c
===================================================================
--- uspace/drv/usbhid/usbhid.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/drv/usbhid/usbhid.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -63,6 +63,4 @@
 static const int USB_HID_MAX_SUBDRIVERS = 10;
 
-static fibril_local bool report_received;
-
 /*----------------------------------------------------------------------------*/
 
@@ -414,5 +412,7 @@
 	}
 	
-	if (fallback) {
+	// TODO: remove the mouse hack
+	if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO ||
+	    fallback) {
 		// fall back to boot protocol
 		switch (hid_dev->poll_pipe_index) {
@@ -509,5 +509,4 @@
 				free(input_old);
 			}
-			usb_hid_new_report();
 		}
 	}
@@ -590,25 +589,4 @@
 /*----------------------------------------------------------------------------*/
 
-void usb_hid_new_report(void)
-{
-	report_received = false;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void usb_hid_report_received(void)
-{
-	report_received = true;
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool usb_hid_report_ready(void)
-{
-	return !report_received;
-}
-
-/*----------------------------------------------------------------------------*/
-
 void usb_hid_free(usb_hid_dev_t **hid_dev)
 {
Index: uspace/drv/usbhid/usbhid.h
===================================================================
--- uspace/drv/usbhid/usbhid.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/drv/usbhid/usbhid.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -44,5 +44,4 @@
 #include <usb/devdrv.h>
 #include <usb/classes/hid.h>
-#include <bool.h>
 
 struct usb_hid_dev;
@@ -129,10 +128,4 @@
 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
 
-void usb_hid_new_report(void);
-
-void usb_hid_report_received(void);
-
-bool usb_hid_report_ready(void);
-
 void usb_hid_free(usb_hid_dev_t **hid_dev);
 
Index: uspace/drv/vhc/transfer.c
===================================================================
--- uspace/drv/vhc/transfer.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/drv/vhc/transfer.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -135,4 +135,5 @@
 		if (transfer->direction == USB_DIRECTION_IN) {
 			rc = usbvirt_ipc_send_control_read(phone,
+			    transfer->endpoint,
 			    transfer->setup_buffer, transfer->setup_buffer_size,
 			    transfer->data_buffer, transfer->data_buffer_size,
@@ -141,4 +142,5 @@
 			assert(transfer->direction == USB_DIRECTION_OUT);
 			rc = usbvirt_ipc_send_control_write(phone,
+			    transfer->endpoint,
 			    transfer->setup_buffer, transfer->setup_buffer_size,
 			    transfer->data_buffer, transfer->data_buffer_size);
Index: uspace/lib/usb/include/usb/classes/hiddescriptor.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hiddescriptor.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usb/include/usb/classes/hiddescriptor.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -78,5 +78,4 @@
 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
 
-usb_hid_report_path_t *usb_hid_report_path_try_insert(usb_hid_report_t *report, usb_hid_report_path_t *cmp_path);
 #endif
 /**
Index: uspace/lib/usb/include/usb/classes/hidpath.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidpath.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usb/include/usb/classes/hidpath.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -43,14 +43,8 @@
  * Description of path of usage pages and usages in report descriptor
  */
-/** Wanted usage path must be exactly the same as the searched one */
-#define USB_HID_PATH_COMPARE_STRICT		0
-/** Wanted usage path must be the suffix in the searched one */
-#define USB_HID_PATH_COMPARE_END		1
-/** */
-#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY	2
-/** Searched usage page must be prefix of the other one */
-#define USB_HID_PATH_COMPARE_BEGIN		4
-/** Searched couple of usage page and usage can be anywhere in usage path */
-#define USB_HID_PATH_COMPARE_ANYWHERE		8
+#define USB_HID_PATH_COMPARE_STRICT				0
+#define USB_HID_PATH_COMPARE_END				1
+#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY	4
+#define USB_HID_PATH_COMPARE_COLLECTION_ONLY	2 /* porovnava jenom cestu z Kolekci */
 
 
Index: uspace/lib/usb/include/usb/classes/hidtypes.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidtypes.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usb/include/usb/classes/hidtypes.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -165,6 +165,4 @@
 	/** */	
 	link_t link;
-
-	int in_delimiter;
 } usb_hid_report_item_t;
 
Index: uspace/lib/usb/src/hiddescriptor.c
===================================================================
--- uspace/lib/usb/src/hiddescriptor.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usb/src/hiddescriptor.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -41,9 +41,4 @@
 #include <assert.h>
 
-
-#define OUTSIDE_DELIMITER_SET	0
-#define START_DELIMITER_SET	1
-#define INSIDE_DELIMITER_SET	2
-	
 /** The new report item flag. Used to determine when the item is completly
  * configured and should be added to the report structure
@@ -61,6 +56,31 @@
 #define USB_HID_UNKNOWN_TAG		-99
 
-usb_hid_report_path_t *usb_hid_report_path_try_insert(usb_hid_report_t *report, usb_hid_report_path_t *cmp_path)
-{
+
+/**
+ * Initialize the report descriptor parser structure
+ *
+ * @param parser Report descriptor parser structure
+ * @return Error code
+ */
+int usb_hid_report_init(usb_hid_report_t *report)
+{
+	if(report == NULL) {
+		return EINVAL;
+	}
+
+	memset(report, 0, sizeof(usb_hid_report_t));
+	list_initialize(&report->reports);
+	list_initialize(&report->collection_paths);
+
+	report->use_report_ids = 0;
+    return EOK;   
+}
+
+int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
+{
+	usb_hid_report_field_t *field;
+	int i;
+
+
 	/* find or append current collection path to the list */
 	link_t *path_it = report->collection_paths.next;
@@ -69,5 +89,5 @@
 		path = list_get_instance(path_it, usb_hid_report_path_t, link);
 		
-		if(usb_hid_report_compare_usage_path(path, cmp_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
+		if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
 			break;
 		}			
@@ -75,44 +95,8 @@
 	}
 	if(path_it == &report->collection_paths) {
-		path = usb_hid_report_path_clone(cmp_path);			
+		path = usb_hid_report_path_clone(report_item->usage_path);			
 		list_append(&path->link, &report->collection_paths);					
 		report->collection_paths_count++;
-
-		return path;
-	}
-	else {
-		return list_get_instance(path_it, usb_hid_report_path_t, link);
-	}
-}
-
-/**
- * Initialize the report descriptor parser structure
- *
- * @param parser Report descriptor parser structure
- * @return Error code
- */
-int usb_hid_report_init(usb_hid_report_t *report)
-{
-	if(report == NULL) {
-		return EINVAL;
-	}
-
-	memset(report, 0, sizeof(usb_hid_report_t));
-	list_initialize(&report->reports);
-	list_initialize(&report->collection_paths);
-
-	report->use_report_ids = 0;
-    return EOK;   
-}
-
-
-/*
- *
- *
- */
-int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
-{
-	usb_hid_report_field_t *field;
-	int i;
+	}
 
 	for(i=0; i<report_item->usages_count; i++){
@@ -120,5 +104,5 @@
 	}
 
-	usb_hid_report_path_t *path = report_item->usage_path;	
+	
 	for(i=0; i<report_item->count; i++){
 
@@ -128,4 +112,5 @@
 
 		/* fill the attributes */		
+		field->collection_path = path;
 		field->logical_minimum = report_item->logical_minimum;
 		field->logical_maximum = report_item->logical_maximum;
@@ -144,9 +129,19 @@
 		if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
 			uint32_t usage;
-			if(i < report_item->usages_count){
-				usage = report_item->usages[i];
+			if(report_item->type != USB_HID_REPORT_TYPE_OUTPUT) {
+				if(i < report_item->usages_count){
+					usage = report_item->usages[i];
+				}
+				else {
+					usage = report_item->usages[report_item->usages_count - 1];
+				}
 			}
 			else {
-				usage = report_item->usages[report_item->usages_count - 1];
+				if((report_item->count - i - 1) < report_item->usages_count){
+					usage = report_item->usages[(report_item->count - i - 1)];
+				}
+				else {
+					usage = report_item->usages[report_item->usages_count - 1];
+				}
 			}
 
@@ -164,18 +159,15 @@
 
 		if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) {
-			field->usage = report_item->usage_minimum + i;					
-		}
-		
-		usb_hid_report_set_last_item(path, USB_HID_TAG_CLASS_GLOBAL, field->usage_page);
-		usb_hid_report_set_last_item(path, USB_HID_TAG_CLASS_LOCAL, field->usage);
-
-		field->collection_path = usb_hid_report_path_try_insert(report, path);
-
+			if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
+				field->usage = report_item->usage_maximum - i;
+			}
+			else {
+				field->usage = report_item->usage_minimum + i;					
+			}
+
+		}
+		
 		field->size = report_item->size;
-		
-		size_t offset_byte = (report_item->offset + (i * report_item->size)) / 8;
-		size_t offset_bit = 8 - ((report_item->offset + (i * report_item->size)) % 8) - report_item->size;
-
-		field->offset = 8 * offset_byte + offset_bit;
+		field->offset = report_item->offset + (i * report_item->size);
 		if(report_item->id != 0) {
 			field->offset += 8;
@@ -272,5 +264,4 @@
 		return ENOMEM;
 	}
-	usb_hid_report_path_append_item(usage_path, 0, 0);	
 	
 	while(i<size){	
@@ -358,6 +349,5 @@
 					tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link);
 					
-					usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL, tmp_usage_path->usage_page);
-					usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL, tmp_usage_path->usage);
+					usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage);
 
 					usb_hid_report_path_free(report_item->usage_path);
@@ -437,7 +427,5 @@
 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
-{
-	usb_hid_report_usage_path_t *path_item;
-	
+{		
 	switch(tag)
 	{
@@ -450,15 +438,6 @@
 			
 		case USB_HID_REPORT_TAG_COLLECTION:
-			// store collection atributes
-			path_item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
-			path_item->flags = *data;	
-			
-			// set last item
-			usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL, report_item->usage_page);
-			usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL, report_item->usages[report_item->usages_count-1]);
-			
-			// append the new one which will be set by common
-			// usage/usage page
-			usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);	
+			// TODO usage_path->flags = *data;
+			usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);						
 			usb_hid_report_reset_local_items (report_item);
 			return USB_HID_NO_ACTION;
@@ -551,17 +530,9 @@
                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
 {
-	switch(tag) {
+	switch(tag)
+	{
 		case USB_HID_REPORT_TAG_USAGE:
-			switch(report_item->in_delimiter) {
-				case INSIDE_DELIMITER_SET:
-					// nothing to do
-					break;
-				case START_DELIMITER_SET:
-					report_item->in_delimiter = INSIDE_DELIMITER_SET;
-				case OUTSIDE_DELIMITER_SET:
-					report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
-					report_item->usages_count++;
-					break;
-			}
+			report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
+			report_item->usages_count++;
 			break;
 		case USB_HID_REPORT_TAG_USAGE_MINIMUM:
@@ -604,11 +575,13 @@
 			break;			
 		case USB_HID_REPORT_TAG_DELIMITER:
-			report_item->in_delimiter = usb_hid_report_tag_data_uint32(data,item_size);
-			break;
-
+			//report_item->delimiter = usb_hid_report_tag_data_uint32(data,item_size);
+			//TODO: 
+			//	DELIMITER STUFF
+			break;
+		
 		default:
 			return USB_HID_NO_ACTION;
 	}
-
+	
 	return EOK;
 }
@@ -656,5 +629,5 @@
 
 		usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
-		usb_log_debug("\t\tSIZE: %zu\n", report_item->size);				
+		usb_log_debug("\t\tSIZE: %zu\n", report_item->size);
 		usb_log_debug("\t\tLOGMIN: %d\n", report_item->logical_minimum);
 		usb_log_debug("\t\tLOGMAX: %d\n", report_item->logical_maximum);		
@@ -667,8 +640,6 @@
 		usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
 		usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
-		
-		//usb_hid_print_usage_path(report_item->collection_path);
-
-		usb_log_debug("\n");		
+						
+//		usb_log_debug("\n");		
 
 	}
@@ -695,6 +666,6 @@
 		usb_log_debug("Report ID: %d\n", report_des->report_id);
 		usb_log_debug("\tType: %d\n", report_des->type);
-		usb_log_debug("\tLength: %zu\n", report_des->bit_length);		
-		usb_log_debug("\tItems: %zu\n", report_des->item_length);		
+		usb_log_debug("\tLength: %zu\n", report_des->bit_length);
+		usb_log_debug("\tItems: %zu\n", report_des->item_length);
 
 		usb_hid_descriptor_print_list(&report_des->report_items);
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usb/src/hidparser.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -405,5 +405,5 @@
 				}
 
-				size_t shift = 8 - offset%8 - length;
+				size_t shift = offset%8;
 
 				value = value << shift;							
Index: uspace/lib/usb/src/hidpath.c
===================================================================
--- uspace/lib/usb/src/hidpath.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usb/src/hidpath.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -149,5 +149,5 @@
 		usb_log_debug("\tFLAGS: %d\n", path_item->flags);		
 		
-       		item = item->next;
+		item = item->next;
 	}
 }
@@ -156,6 +156,7 @@
  * Compares two usage paths structures
  *
- *
- * @param report_path usage path structure to compare with @path 
+ * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten
+ *
+ * @param report_path usage path structure to compare
  * @param path usage patrh structure to compare
  * @param flags Flags determining the mode of comparison
@@ -178,5 +179,4 @@
 	}
 
-	// Empty path match all others
 	if(path->depth == 0){
 		return EOK;
@@ -189,43 +189,10 @@
 	
 	switch(flags){
-		/* path is somewhere in report_path */
-		case USB_HID_PATH_COMPARE_ANYWHERE:
-			if(path->depth != 1){
-				return 1;
-			}
-
-			// projit skrz cestu a kdyz nekde sedi tak vratim EOK
-			// dojduli az za konec tak nnesedi
-			report_link = report_path->head.next;
-			path_link = path->head.next;
-			path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
-
-			while(report_link != &report_path->head) {
-				report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
-				if(report_item->usage_page == path_item->usage_page){
-					if(only_page == 0){
-						if(report_item->usage == path_item->usage) {
-							return EOK;
-						}
-					}
-					else {
-						return EOK;
-					}
-				}
-
-				report_link = report_link->next;
-			}
-
-			return 1;
-			break;
-		/* the paths must be identical */
+		/* path must be completly identical */
 		case USB_HID_PATH_COMPARE_STRICT:
 				if(report_path->depth != path->depth){
 					return 1;
 				}
-		
-		/* path is prefix of the report_path */
-		case USB_HID_PATH_COMPARE_BEGIN:
-	
+
 				report_link = report_path->head.next;
 				path_link = path->head.next;
@@ -254,6 +221,8 @@
 				}
 
-				if((((flags & USB_HID_PATH_COMPARE_BEGIN) != 0) && (path_link == &path->head)) || 
-				   ((report_link == &report_path->head) && (path_link == &path->head))) {
+				if(((report_link == &report_path->head) && (path_link == &path->head)) || 
+				   (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && 
+				    (path_link = &path->head) && 
+				    (report_link == report_path->head.prev))) {
 					return EOK;
 				}
@@ -263,8 +232,13 @@
 			break;
 
-		/* path is suffix of report_path */
+		/* compare with only the end of path*/
 		case USB_HID_PATH_COMPARE_END:
 
-				report_link = report_path->head.prev;
+				if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) {
+					report_link = report_path->head.prev->prev;
+				}
+				else {
+					report_link = report_path->head.prev;
+				}
 				path_link = path->head.prev;
 
Index: uspace/lib/usbvirt/Makefile
===================================================================
--- uspace/lib/usbvirt/Makefile	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usbvirt/Makefile	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -33,8 +33,6 @@
 
 SOURCES = \
+	src/ipc.c \
 	src/ctrltransfer.c \
-	src/device.c \
-	src/ipc_dev.c \
-	src/ipc_hc.c \
 	src/stdreq.c \
 	src/transfer.c
Index: uspace/lib/usbvirt/include/usbvirt/device.h
===================================================================
--- uspace/lib/usbvirt/include/usbvirt/device.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usbvirt/include/usbvirt/device.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -31,5 +31,5 @@
  */
 /** @file
- * Virtual USB device.
+ * @brief Virtual USB device.
  */
 #ifndef LIBUSBVIRT_DEVICE_H_
@@ -39,68 +39,21 @@
 #include <usb/request.h>
 
-/** Maximum number of endpoints supported by virtual USB. */
 #define USBVIRT_ENDPOINT_MAX 16
 
 typedef struct usbvirt_device usbvirt_device_t;
 
-/** Callback for data to device (OUT transaction).
- *
- * @param dev Virtual device to which the transaction belongs.
- * @param endpoint Target endpoint number.
- * @param transfer_type Transfer type.
- * @param buffer Data buffer.
- * @param buffer_size Size of the buffer in bytes.
- * @return Error code.
- */
-typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *dev,
-    usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
-    void *buffer, size_t buffer_size);
+typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *, usb_endpoint_t,
+    usb_transfer_type_t, void *, size_t);
+typedef int (*usbvirt_on_data_from_device_t)(usbvirt_device_t *, usb_endpoint_t,
+    usb_transfer_type_t, void *, size_t, size_t *);
+typedef int (*usbvirt_on_control_t)(usbvirt_device_t *,
+    const usb_device_request_setup_packet_t *, uint8_t *, size_t *);
 
-/** Callback for data from device (IN transaction).
- *
- * @param dev Virtual device to which the transaction belongs.
- * @param endpoint Target endpoint number.
- * @param transfer_type Transfer type.
- * @param buffer Data buffer to write answer to.
- * @param buffer_size Size of the buffer in bytes.
- * @param act_buffer_size Write here how many bytes were actually written.
- * @return Error code.
- */
-typedef int (*usbvirt_on_data_from_device_t)(usbvirt_device_t *dev,
-    usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
-    void *buffer, size_t buffer_size, size_t *act_buffer_size);
-
-/** Callback for control transfer on endpoint zero.
- *
- * Notice that size of the data buffer is expected to be read from the
- * setup packet.
- *
- * @param dev Virtual device to which the transaction belongs.
- * @param setup_packet Standard setup packet.
- * @param data Data (might be NULL).
- * @param act_data_size Size of returned data in bytes.
- * @return Error code.
- */
-typedef int (*usbvirt_on_control_t)(usbvirt_device_t *dev,
-    const usb_device_request_setup_packet_t *setup_packet,
-    uint8_t *data, size_t *act_data_size);
-
-/** Callback for control request on a virtual USB device.
- *
- * See usbvirt_control_reply_helper() for simple way of answering
- * control read requests.
- */
 typedef struct {
-	/** Request direction (in or out). */
 	usb_direction_t req_direction;
-	/** Request recipient (device, interface or endpoint). */
 	usb_request_recipient_t req_recipient;
-	/** Request type (standard, class or vendor). */
 	usb_request_type_t req_type;
-	/** Actual request code. */
 	uint8_t request;
-	/** Request handler name for debugging purposes. */
 	const char *name;
-	/** Callback to be executed on matching request. */
 	usbvirt_on_control_t callback;
 } usbvirt_control_request_handler_t;
@@ -124,5 +77,5 @@
 } usbvirt_device_configuration_t;
 
-/** Standard USB descriptors for virtual device. */
+/** Standard USB descriptors. */
 typedef struct {
 	/** Standard device descriptor.
@@ -149,57 +102,22 @@
 } usbvirt_device_state_t;
 
-/** Ops structure for virtual USB device. */
 typedef struct {
-	/** Callbacks for data to device.
-	 * Index zero is ignored.
-	 */
 	usbvirt_on_data_to_device_t data_out[USBVIRT_ENDPOINT_MAX];
-	/** Callbacks for data from device.
-	 * Index zero is ignored.
-	 */
 	usbvirt_on_data_from_device_t data_in[USBVIRT_ENDPOINT_MAX];
-	/** Array of control handlers.
-	 * Last handler is expected to have the @c callback field set to NULL
-	 */
 	usbvirt_control_request_handler_t *control;
-	/** Callback when device changes state.
-	 *
-	 * The value of @c state attribute of @p dev device is not
-	 * defined during call of this function.
-	 *
-	 * @param dev The virtual USB device.
-	 * @param old_state Old device state.
-	 * @param new_state New device state.
-	 */
 	void (*state_changed)(usbvirt_device_t *dev,
 	    usbvirt_device_state_t old_state, usbvirt_device_state_t new_state);
 } usbvirt_device_ops_t;
 
-/** Virtual USB device. */
 struct usbvirt_device {
-	/** Name for debugging purposes. */
 	const char *name;
-	/** Custom device data. */
 	void *device_data;
-	/** Device ops. */
 	usbvirt_device_ops_t *ops;
-	/** Device descriptors. */
 	usbvirt_descriptors_t *descriptors;
-	/** Current device address.
-	 * You shall treat this field as read only in your code.
-	 */
 	usb_address_t address;
-	/** Current device state.
-	 * You shall treat this field as read only in your code.
-	 */
 	usbvirt_device_state_t state;
-	/** Phone to the host controller.
-	 * You shall treat this field as read only in your code.
-	 */
-	int vhc_phone;
 };
 
 int usbvirt_device_plug(usbvirt_device_t *, const char *);
-void usbvirt_device_unplug(usbvirt_device_t *);
 
 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *,
Index: uspace/lib/usbvirt/include/usbvirt/ipc.h
===================================================================
--- uspace/lib/usbvirt/include/usbvirt/ipc.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usbvirt/include/usbvirt/ipc.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2010 Vojtech Horky
  * All rights reserved.
  *
@@ -31,5 +31,5 @@
  */
 /** @file
- * IPC wrappers for virtual USB.
+ * @brief Virtual USB device.
  */
 #ifndef LIBUSBVIRT_IPC_H_
@@ -40,5 +40,4 @@
 #include <bool.h>
 
-/** IPC methods communication between host controller and virtual device. */
 typedef enum {
 	IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD + 80,
@@ -46,12 +45,10 @@
 	IPC_M_USBVIRT_CONTROL_WRITE,
 	IPC_M_USBVIRT_INTERRUPT_IN,
-	IPC_M_USBVIRT_INTERRUPT_OUT,
-	IPC_M_USBVIRT_BULK_IN,
-	IPC_M_USBVIRT_BULK_OUT
-} usbvirt_hc_to_device_method_t;
+	IPC_M_USBVIRT_INTERRUPT_OUT
+} usbvirt_ipc_t;
 
-int usbvirt_ipc_send_control_read(int, void *, size_t,
+int usbvirt_ipc_send_control_read(int, usb_endpoint_t, void *, size_t,
     void *, size_t, size_t *);
-int usbvirt_ipc_send_control_write(int, void *, size_t,
+int usbvirt_ipc_send_control_write(int, usb_endpoint_t, void *, size_t,
     void *, size_t);
 int usbvirt_ipc_send_data_in(int, usb_endpoint_t, usb_transfer_type_t,
Index: uspace/lib/usbvirt/src/ctrltransfer.c
===================================================================
--- uspace/lib/usbvirt/src/ctrltransfer.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usbvirt/src/ctrltransfer.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -1,36 +1,2 @@
-/*
- * Copyright (c) 2011 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
- * @{
- */
-/** @file
- * Control transfer handling.
- */
 #include "private.h"
 #include <usb/request.h>
@@ -39,14 +5,4 @@
 #include <errno.h>
 
-/** Find and execute control transfer handler for virtual USB device.
- *
- * @param dev Target virtual device.
- * @param control_handlers Array of control request handlers.
- * @param setup Setup packet.
- * @param data Extra data.
- * @param data_sent_size Size of extra data in bytes.
- * @return Error code.
- * @retval EFORWARD No suitable handler found.
- */
 int process_control_transfer(usbvirt_device_t *dev,
     usbvirt_control_request_handler_t *control_handlers,
@@ -96,7 +52,2 @@
 	return EFORWARD;
 }
-
-
-/**
- * @}
- */
Index: pace/lib/usbvirt/src/device.c
===================================================================
--- uspace/lib/usbvirt/src/device.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ 	(revision )
@@ -1,127 +1,0 @@
-/*
- * Copyright (c) 2011 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
- * @{
- */
-/** @file
- * Virtual USB device main routines.
- */
-#include <errno.h>
-#include <str.h>
-#include <stdio.h>
-#include <assert.h>
-#include <async.h>
-#include <devman.h>
-#include <usbvirt/device.h>
-#include <usbvirt/ipc.h>
-
-#include <usb/debug.h>
-
-/** Current device. */
-static usbvirt_device_t *DEV = NULL;
-
-/** Main IPC call handling from virtual host controller.
- *
- * @param iid Caller identification.
- * @param icall Initial incoming call.
- */
-static void callback_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	assert(DEV != NULL);
-
-	async_answer_0(iid, EOK);
-
-	while (true) {
-		ipc_callid_t callid;
-		ipc_call_t call;
-
-		callid = async_get_call(&call);
-		bool processed = usbvirt_ipc_handle_call(DEV, callid, &call);
-		if (!processed) {
-			switch (IPC_GET_IMETHOD(call)) {
-				case IPC_M_PHONE_HUNGUP:
-					async_answer_0(callid, EOK);
-					return;
-				default:
-					async_answer_0(callid, EINVAL);
-					break;
-			}
-		}
-	}
-}
-
-/** Connect the device to the virtual host controller.
- *
- * @param dev The virtual device to be (virtually) plugged in.
- * @param vhc_path Devman path to the virtual host controller.
- * @return Error code.
- */
-int usbvirt_device_plug(usbvirt_device_t *dev, const char *vhc_path)
-{
-	int rc;
-	devman_handle_t handle;
-
-	if (DEV != NULL) {
-		return ELIMIT;
-	}
-
-	rc = devman_device_get_handle(vhc_path, &handle, 0);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	int hcd_phone = devman_device_connect(handle, 0);
-
-	if (hcd_phone < 0) {
-		return hcd_phone;
-	}
-
-	DEV = dev;
-	dev->vhc_phone = hcd_phone;
-
-	rc = async_connect_to_me(hcd_phone, 0, 0, 0, callback_connection);
-	if (rc != EOK) {
-		DEV = NULL;
-	}
-
-	return rc;
-}
-
-/** Disconnect the device from virtual host controller.
- *
- * @param dev Device to be disconnected.
- */
-void usbvirt_device_unplug(usbvirt_device_t *dev)
-{
-	async_hangup(dev->vhc_phone);
-}
-
-/**
- * @}
- */
Index: uspace/lib/usbvirt/src/ipc.c
===================================================================
--- uspace/lib/usbvirt/src/ipc.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
+++ uspace/lib/usbvirt/src/ipc.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2011 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
+ * @{
+ */
+/** @file
+ *
+ */
+#include <errno.h>
+#include <str.h>
+#include <stdio.h>
+#include <assert.h>
+#include <async.h>
+#include <devman.h>
+#include <usbvirt/device.h>
+#include <usbvirt/ipc.h>
+
+#include <usb/debug.h>
+
+static usbvirt_device_t *DEV = NULL;
+
+static void ipc_get_name(usbvirt_device_t *dev,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	if (dev->name == NULL) {
+		async_answer_0(iid, ENOENT);
+	}
+
+	size_t size = str_size(dev->name);
+
+	ipc_callid_t callid;
+	size_t accepted_size;
+	if (!async_data_read_receive(&callid, &accepted_size)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	if (accepted_size > size) {
+		accepted_size = size;
+	}
+	async_data_read_finalize(callid, dev->name, accepted_size);
+
+	async_answer_1(iid, EOK, accepted_size);
+}
+
+static void ipc_control_read(usbvirt_device_t *dev,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	//usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
+
+	int rc;
+
+	void *setup_packet = NULL;
+	size_t setup_packet_len = 0;
+	size_t data_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, 1024, 0, &setup_packet_len);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EPARTY);
+		free(setup_packet);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(iid, ENOMEM);
+		free(setup_packet);
+		return;
+	}
+
+	size_t actual_len;
+	rc = usbvirt_control_read(dev, setup_packet, setup_packet_len,
+	    buffer, data_len, &actual_len);
+
+	if (rc != EOK) {
+		async_answer_0(data_callid, rc);
+		async_answer_0(iid, rc);
+		free(setup_packet);
+		free(buffer);
+		return;
+	}
+
+	async_data_read_finalize(data_callid, buffer, actual_len);
+	async_answer_0(iid, EOK);
+
+	free(setup_packet);
+	free(buffer);
+}
+
+static void ipc_control_write(usbvirt_device_t *dev,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	size_t data_buffer_len = IPC_GET_ARG2(*icall);
+	int rc;
+
+	void *setup_packet = NULL;
+	void *data_buffer = NULL;
+	size_t setup_packet_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, 1024, 0, &setup_packet_len);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	if (data_buffer_len > 0) {
+		rc = async_data_write_accept(&data_buffer, false,
+		    1, 1024, 0, &data_buffer_len);
+		if (rc != EOK) {
+			async_answer_0(iid, rc);
+			free(setup_packet);
+			return;
+		}
+	}
+
+	rc = usbvirt_control_write(dev, setup_packet, setup_packet_len,
+	    data_buffer, data_buffer_len);
+
+	async_answer_0(iid, rc);
+}
+
+static void ipc_interrupt_in(usbvirt_device_t *dev,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
+	usb_transfer_type_t transfer_type = IPC_GET_ARG2(*icall);
+
+	int rc;
+
+	size_t data_len = 0;
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EPARTY);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	size_t actual_len;
+	rc = usbvirt_data_in(dev, transfer_type, endpoint,
+	    buffer, data_len, &actual_len);
+
+	if (rc != EOK) {
+		async_answer_0(data_callid, rc);
+		async_answer_0(iid, rc);
+		free(buffer);
+		return;
+	}
+
+	async_data_read_finalize(data_callid, buffer, actual_len);
+	async_answer_0(iid, EOK);
+
+	free(buffer);
+}
+
+static void ipc_interrupt_out(usbvirt_device_t *dev,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
+	usb_transfer_type_t transfer_type = IPC_GET_ARG2(*icall);
+
+	void *data_buffer = NULL;
+	size_t data_buffer_size = 0;
+
+	int rc = async_data_write_accept(&data_buffer, false,
+	    1, 1024, 0, &data_buffer_size);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	rc = usbvirt_data_out(dev, transfer_type, endpoint,
+	    data_buffer, data_buffer_size);
+
+	async_answer_0(iid, rc);
+
+	free(data_buffer);
+}
+
+
+bool usbvirt_ipc_handle_call(usbvirt_device_t *dev,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	switch (IPC_GET_IMETHOD(*call)) {
+		case IPC_M_USBVIRT_GET_NAME:
+			ipc_get_name(dev, callid, call);
+			break;
+
+		case IPC_M_USBVIRT_CONTROL_READ:
+			ipc_control_read(dev, callid, call);
+			break;
+
+		case IPC_M_USBVIRT_CONTROL_WRITE:
+			ipc_control_write(dev, callid, call);
+			break;
+
+		case IPC_M_USBVIRT_INTERRUPT_IN:
+			ipc_interrupt_in(dev, callid, call);
+			break;
+
+		case IPC_M_USBVIRT_INTERRUPT_OUT:
+			ipc_interrupt_out(dev, callid, call);
+			break;
+
+		default:
+			return false;
+	}
+
+	return true;
+}
+
+static void callback_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	assert(DEV != NULL);
+
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_callid_t callid;
+		ipc_call_t call;
+
+		callid = async_get_call(&call);
+		bool processed = usbvirt_ipc_handle_call(DEV, callid, &call);
+		if (!processed) {
+			switch (IPC_GET_IMETHOD(call)) {
+				case IPC_M_PHONE_HUNGUP:
+					async_answer_0(callid, EOK);
+					return;
+				default:
+					async_answer_0(callid, EINVAL);
+					break;
+			}
+		}
+	}
+}
+
+int usbvirt_device_plug(usbvirt_device_t *dev, const char *vhc_path)
+{
+	int rc;
+	devman_handle_t handle;
+
+	rc = devman_device_get_handle(vhc_path, &handle, 0);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	int hcd_phone = devman_device_connect(handle, 0);
+
+	if (hcd_phone < 0) {
+		return hcd_phone;
+	}
+
+	DEV = dev;
+
+	rc = async_connect_to_me(hcd_phone, 0, 0, 0, callback_connection);
+	if (rc != EOK) {
+		DEV = NULL;
+		return rc;
+	}
+
+
+
+	return EOK;
+}
+
+
+
+int usbvirt_ipc_send_control_read(int phone, usb_endpoint_t ep,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	aid_t opening_request = async_send_1(phone,
+	    IPC_M_USBVIRT_CONTROL_READ, ep, NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	int rc = async_data_write_start(phone,
+	    setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(phone,
+	    data_buffer, data_buffer_size,
+	    &data_request_call);
+
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		/* Prefer the return code of the opening request. */
+		if (opening_request_rc != EOK) {
+			return (int) opening_request_rc;
+		} else {
+			return (int) data_request_rc;
+		}
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*data_transfered_size = IPC_GET_ARG2(data_request_call);
+
+	return EOK;
+}
+
+int usbvirt_ipc_send_control_write(int phone, usb_endpoint_t ep,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	aid_t opening_request = async_send_2(phone,
+	    IPC_M_USBVIRT_CONTROL_WRITE, ep, data_buffer_size,  NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	int rc = async_data_write_start(phone,
+	    setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	if (data_buffer_size > 0) {
+		rc = async_data_write_start(phone,
+		    data_buffer, data_buffer_size);
+
+		if (rc != EOK) {
+			async_wait_for(opening_request, NULL);
+			return rc;
+		}
+	}
+
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+int usbvirt_ipc_send_data_in(int phone, usb_endpoint_t ep,
+    usb_transfer_type_t tr_type, void *data, size_t data_size, size_t *act_size)
+{
+	aid_t opening_request = async_send_2(phone,
+	    IPC_M_USBVIRT_INTERRUPT_IN, ep, tr_type, NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(phone,
+	    data, data_size,  &data_request_call);
+
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		/* Prefer the return code of the opening request. */
+		if (opening_request_rc != EOK) {
+			return (int) opening_request_rc;
+		} else {
+			return (int) data_request_rc;
+		}
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	if (act_size != NULL) {
+		*act_size = IPC_GET_ARG2(data_request_call);
+	}
+
+	return EOK;
+}
+
+int usbvirt_ipc_send_data_out(int phone, usb_endpoint_t ep,
+    usb_transfer_type_t tr_type, void *data, size_t data_size)
+{
+	aid_t opening_request = async_send_2(phone,
+	    IPC_M_USBVIRT_INTERRUPT_OUT, ep, tr_type, NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	int rc = async_data_write_start(phone,
+	    data, data_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+
+/**
+ * @}
+ */
Index: pace/lib/usbvirt/src/ipc_dev.c
===================================================================
--- uspace/lib/usbvirt/src/ipc_dev.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ 	(revision )
@@ -1,297 +1,0 @@
-/*
- * Copyright (c) 2011 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
- * @{
- */
-/** @file
- * IPC wrappers, device side.
- */
-#include <errno.h>
-#include <str.h>
-#include <stdio.h>
-#include <assert.h>
-#include <async.h>
-#include <devman.h>
-#include <usbvirt/device.h>
-#include <usbvirt/ipc.h>
-#include <usb/debug.h>
-
-/** Handle VHC request for device name.
- *
- * @param dev Target virtual device.
- * @param iid Caller id.
- * @param icall The call with the request.
- */
-static void ipc_get_name(usbvirt_device_t *dev,
-    ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (dev->name == NULL) {
-		async_answer_0(iid, ENOENT);
-	}
-
-	size_t size = str_size(dev->name);
-
-	ipc_callid_t callid;
-	size_t accepted_size;
-	if (!async_data_read_receive(&callid, &accepted_size)) {
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-
-	if (accepted_size > size) {
-		accepted_size = size;
-	}
-	async_data_read_finalize(callid, dev->name, accepted_size);
-
-	async_answer_1(iid, EOK, accepted_size);
-}
-
-/** Handle VHC request for control read from the device.
- *
- * @param dev Target virtual device.
- * @param iid Caller id.
- * @param icall The call with the request.
- */
-static void ipc_control_read(usbvirt_device_t *dev,
-    ipc_callid_t iid, ipc_call_t *icall)
-{
-	int rc;
-
-	void *setup_packet = NULL;
-	size_t setup_packet_len = 0;
-	size_t data_len = 0;
-
-	rc = async_data_write_accept(&setup_packet, false,
-	    1, 1024, 0, &setup_packet_len);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-
-	ipc_callid_t data_callid;
-	if (!async_data_read_receive(&data_callid, &data_len)) {
-		async_answer_0(iid, EPARTY);
-		free(setup_packet);
-		return;
-	}
-
-	void *buffer = malloc(data_len);
-	if (buffer == NULL) {
-		async_answer_0(iid, ENOMEM);
-		free(setup_packet);
-		return;
-	}
-
-	size_t actual_len;
-	rc = usbvirt_control_read(dev, setup_packet, setup_packet_len,
-	    buffer, data_len, &actual_len);
-
-	if (rc != EOK) {
-		async_answer_0(data_callid, rc);
-		async_answer_0(iid, rc);
-		free(setup_packet);
-		free(buffer);
-		return;
-	}
-
-	async_data_read_finalize(data_callid, buffer, actual_len);
-	async_answer_0(iid, EOK);
-
-	free(setup_packet);
-	free(buffer);
-}
-
-/** Handle VHC request for control write to the device.
- *
- * @param dev Target virtual device.
- * @param iid Caller id.
- * @param icall The call with the request.
- */
-static void ipc_control_write(usbvirt_device_t *dev,
-    ipc_callid_t iid, ipc_call_t *icall)
-{
-	size_t data_buffer_len = IPC_GET_ARG1(*icall);
-	int rc;
-
-	void *setup_packet = NULL;
-	void *data_buffer = NULL;
-	size_t setup_packet_len = 0;
-
-	rc = async_data_write_accept(&setup_packet, false,
-	    1, 0, 0, &setup_packet_len);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-
-	if (data_buffer_len > 0) {
-		rc = async_data_write_accept(&data_buffer, false,
-		    1, 0, 0, &data_buffer_len);
-		if (rc != EOK) {
-			async_answer_0(iid, rc);
-			free(setup_packet);
-			return;
-		}
-	}
-
-	rc = usbvirt_control_write(dev, setup_packet, setup_packet_len,
-	    data_buffer, data_buffer_len);
-
-	async_answer_0(iid, rc);
-
-	free(setup_packet);
-	if (data_buffer != NULL) {
-		free(data_buffer);
-	}
-}
-
-/** Handle VHC request for data read from the device (in transfer).
- *
- * @param dev Target virtual device.
- * @param iid Caller id.
- * @param icall The call with the request.
- */
-static void ipc_data_in(usbvirt_device_t *dev,
-    usb_transfer_type_t transfer_type,
-    ipc_callid_t iid, ipc_call_t *icall)
-{
-	usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
-
-	int rc;
-
-	size_t data_len = 0;
-	ipc_callid_t data_callid;
-	if (!async_data_read_receive(&data_callid, &data_len)) {
-		async_answer_0(iid, EPARTY);
-		return;
-	}
-
-	void *buffer = malloc(data_len);
-	if (buffer == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-
-	size_t actual_len;
-	rc = usbvirt_data_in(dev, transfer_type, endpoint,
-	    buffer, data_len, &actual_len);
-
-	if (rc != EOK) {
-		async_answer_0(data_callid, rc);
-		async_answer_0(iid, rc);
-		free(buffer);
-		return;
-	}
-
-	async_data_read_finalize(data_callid, buffer, actual_len);
-	async_answer_0(iid, EOK);
-
-	free(buffer);
-}
-
-/** Handle VHC request for data write to the device (out transfer).
- *
- * @param dev Target virtual device.
- * @param iid Caller id.
- * @param icall The call with the request.
- */
-static void ipc_data_out(usbvirt_device_t *dev,
-    usb_transfer_type_t transfer_type,
-    ipc_callid_t iid, ipc_call_t *icall)
-{
-	usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
-
-	void *data_buffer = NULL;
-	size_t data_buffer_size = 0;
-
-	int rc = async_data_write_accept(&data_buffer, false,
-	    1, 0, 0, &data_buffer_size);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-
-	rc = usbvirt_data_out(dev, transfer_type, endpoint,
-	    data_buffer, data_buffer_size);
-
-	async_answer_0(iid, rc);
-
-	free(data_buffer);
-}
-
-/** Handle incoming IPC call for virtual USB device.
- *
- * @param dev Target USB device.
- * @param callid Caller id.
- * @param call Incoming call.
- * @return Whether the call was handled.
- */
-bool usbvirt_ipc_handle_call(usbvirt_device_t *dev,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_USBVIRT_GET_NAME:
-		ipc_get_name(dev, callid, call);
-		break;
-
-	case IPC_M_USBVIRT_CONTROL_READ:
-		ipc_control_read(dev, callid, call);
-		break;
-
-	case IPC_M_USBVIRT_CONTROL_WRITE:
-		ipc_control_write(dev, callid, call);
-		break;
-
-	case IPC_M_USBVIRT_INTERRUPT_IN:
-		ipc_data_in(dev, USB_TRANSFER_INTERRUPT, callid, call);
-		break;
-
-	case IPC_M_USBVIRT_BULK_IN:
-		ipc_data_in(dev, USB_TRANSFER_BULK, callid, call);
-		break;
-
-	case IPC_M_USBVIRT_INTERRUPT_OUT:
-		ipc_data_out(dev, USB_TRANSFER_INTERRUPT, callid, call);
-		break;
-
-	case IPC_M_USBVIRT_BULK_OUT:
-		ipc_data_out(dev, USB_TRANSFER_BULK, callid, call);
-		break;
-
-
-	default:
-		return false;
-	}
-
-	return true;
-}
-
-/**
- * @}
- */
Index: pace/lib/usbvirt/src/ipc_hc.c
===================================================================
--- uspace/lib/usbvirt/src/ipc_hc.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ 	(revision )
@@ -1,298 +1,0 @@
-/*
- * Copyright (c) 2011 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
- * @{
- */
-/** @file
- * IPC wrappers, host controller side.
- */
-#include <errno.h>
-#include <str.h>
-#include <stdio.h>
-#include <assert.h>
-#include <async.h>
-#include <devman.h>
-#include <usbvirt/device.h>
-#include <usbvirt/ipc.h>
-#include <usb/debug.h>
-
-/** Send control read transfer to virtual USB device.
- *
- * @param phone IPC phone to the virtual device.
- * @param ep Target endpoint number.
- * @param setup_buffer Setup buffer.
- * @param setup_buffer_size Setup buffer size in bytes.
- * @param data_buffer Data buffer (DATA stage of control transfer).
- * @param data_buffer_size Size of data buffer in bytes.
- * @param data_transfered_size Number of actually transferred bytes.
- * @return Error code.
- */
-int usbvirt_ipc_send_control_read(int phone,
-    void *setup_buffer, size_t setup_buffer_size,
-    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
-		return EINVAL;
-	}
-	if ((data_buffer == NULL) || (data_buffer_size == 0)) {
-		return EINVAL;
-	}
-
-	aid_t opening_request = async_send_0(phone,
-	    IPC_M_USBVIRT_CONTROL_READ, NULL);
-	if (opening_request == 0) {
-		return ENOMEM;
-	}
-
-	int rc = async_data_write_start(phone,
-	    setup_buffer, setup_buffer_size);
-	if (rc != EOK) {
-		async_wait_for(opening_request, NULL);
-		return rc;
-	}
-
-	ipc_call_t data_request_call;
-	aid_t data_request = async_data_read(phone,
-	    data_buffer, data_buffer_size,
-	    &data_request_call);
-
-	if (data_request == 0) {
-		async_wait_for(opening_request, NULL);
-		return ENOMEM;
-	}
-
-	sysarg_t data_request_rc;
-	sysarg_t opening_request_rc;
-	async_wait_for(data_request, &data_request_rc);
-	async_wait_for(opening_request, &opening_request_rc);
-
-	if (data_request_rc != EOK) {
-		/* Prefer the return code of the opening request. */
-		if (opening_request_rc != EOK) {
-			return (int) opening_request_rc;
-		} else {
-			return (int) data_request_rc;
-		}
-	}
-	if (opening_request_rc != EOK) {
-		return (int) opening_request_rc;
-	}
-
-	if (data_transfered_size != NULL) {
-		*data_transfered_size = IPC_GET_ARG2(data_request_call);
-	}
-
-	return EOK;
-}
-
-/** Send control write transfer to virtual USB device.
- *
- * @param phone IPC phone to the virtual device.
- * @param ep Target endpoint number.
- * @param setup_buffer Setup buffer.
- * @param setup_buffer_size Setup buffer size in bytes.
- * @param data_buffer Data buffer (DATA stage of control transfer).
- * @param data_buffer_size Size of data buffer in bytes.
- * @return Error code.
- */
-int usbvirt_ipc_send_control_write(int phone,
-    void *setup_buffer, size_t setup_buffer_size,
-    void *data_buffer, size_t data_buffer_size)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
-		return EINVAL;
-	}
-	if ((data_buffer_size > 0) && (data_buffer == NULL)) {
-		return EINVAL;
-	}
-
-	aid_t opening_request = async_send_1(phone,
-	    IPC_M_USBVIRT_CONTROL_WRITE, data_buffer_size,  NULL);
-	if (opening_request == 0) {
-		return ENOMEM;
-	}
-
-	int rc = async_data_write_start(phone,
-	    setup_buffer, setup_buffer_size);
-	if (rc != EOK) {
-		async_wait_for(opening_request, NULL);
-		return rc;
-	}
-
-	if (data_buffer_size > 0) {
-		rc = async_data_write_start(phone,
-		    data_buffer, data_buffer_size);
-
-		if (rc != EOK) {
-			async_wait_for(opening_request, NULL);
-			return rc;
-		}
-	}
-
-	sysarg_t opening_request_rc;
-	async_wait_for(opening_request, &opening_request_rc);
-
-	return (int) opening_request_rc;
-}
-
-/** Request data transfer from virtual USB device.
- *
- * @param phone IPC phone to the virtual device.
- * @param ep Target endpoint number.
- * @param tr_type Transfer type (interrupt or bulk).
- * @param data Data buffer.
- * @param data_size Size of the data buffer in bytes.
- * @param act_size Number of actually returned bytes.
- * @return Error code.
- */
-int usbvirt_ipc_send_data_in(int phone, usb_endpoint_t ep,
-    usb_transfer_type_t tr_type, void *data, size_t data_size, size_t *act_size)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-	usbvirt_hc_to_device_method_t method;
-	switch (tr_type) {
-	case USB_TRANSFER_INTERRUPT:
-		method = IPC_M_USBVIRT_INTERRUPT_IN;
-		break;
-	case USB_TRANSFER_BULK:
-		method = IPC_M_USBVIRT_BULK_IN;
-		break;
-	default:
-		return EINVAL;
-	}
-	if ((ep <= 0) || (ep >= USBVIRT_ENDPOINT_MAX)) {
-		return EINVAL;
-	}
-	if ((data == NULL) || (data_size == 0)) {
-		return EINVAL;
-	}
-
-
-	aid_t opening_request = async_send_2(phone, method, ep, tr_type, NULL);
-	if (opening_request == 0) {
-		return ENOMEM;
-	}
-
-
-	ipc_call_t data_request_call;
-	aid_t data_request = async_data_read(phone,
-	    data, data_size,  &data_request_call);
-
-	if (data_request == 0) {
-		async_wait_for(opening_request, NULL);
-		return ENOMEM;
-	}
-
-	sysarg_t data_request_rc;
-	sysarg_t opening_request_rc;
-	async_wait_for(data_request, &data_request_rc);
-	async_wait_for(opening_request, &opening_request_rc);
-
-	if (data_request_rc != EOK) {
-		/* Prefer the return code of the opening request. */
-		if (opening_request_rc != EOK) {
-			return (int) opening_request_rc;
-		} else {
-			return (int) data_request_rc;
-		}
-	}
-	if (opening_request_rc != EOK) {
-		return (int) opening_request_rc;
-	}
-
-	if (act_size != NULL) {
-		*act_size = IPC_GET_ARG2(data_request_call);
-	}
-
-	return EOK;
-}
-
-/** Send data to virtual USB device.
- *
- * @param phone IPC phone to the virtual device.
- * @param ep Target endpoint number.
- * @param tr_type Transfer type (interrupt or bulk).
- * @param data Data buffer.
- * @param data_size Size of the data buffer in bytes.
- * @return Error code.
- */
-int usbvirt_ipc_send_data_out(int phone, usb_endpoint_t ep,
-    usb_transfer_type_t tr_type, void *data, size_t data_size)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-	usbvirt_hc_to_device_method_t method;
-	switch (tr_type) {
-	case USB_TRANSFER_INTERRUPT:
-		method = IPC_M_USBVIRT_INTERRUPT_OUT;
-		break;
-	case USB_TRANSFER_BULK:
-		method = IPC_M_USBVIRT_BULK_OUT;
-		break;
-	default:
-		return EINVAL;
-	}
-	if ((ep <= 0) || (ep >= USBVIRT_ENDPOINT_MAX)) {
-		return EINVAL;
-	}
-	if ((data == NULL) || (data_size == 0)) {
-		return EINVAL;
-	}
-
-	aid_t opening_request = async_send_1(phone, method, ep, NULL);
-	if (opening_request == 0) {
-		return ENOMEM;
-	}
-
-	int rc = async_data_write_start(phone,
-	    data, data_size);
-	if (rc != EOK) {
-		async_wait_for(opening_request, NULL);
-		return rc;
-	}
-
-	sysarg_t opening_request_rc;
-	async_wait_for(opening_request, &opening_request_rc);
-
-	return (int) opening_request_rc;
-}
-
-
-/**
- * @}
- */
Index: uspace/lib/usbvirt/src/private.h
===================================================================
--- uspace/lib/usbvirt/src/private.h	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usbvirt/src/private.h	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -1,39 +1,2 @@
-/*
- * Copyright (c) 2011 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
- * @{
- */
-/** @file
- * Private definitions.
- */
-#ifndef USBVIRT_PRIVATE_H_
-#define USBVIRT_PRIVATE_H_
-
 #include <usbvirt/device.h>
 
@@ -44,7 +7,2 @@
 
 extern usbvirt_control_request_handler_t library_handlers[];
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/usbvirt/src/stdreq.c
===================================================================
--- uspace/lib/usbvirt/src/stdreq.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usbvirt/src/stdreq.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -1,36 +1,2 @@
-/*
- * Copyright (c) 2011 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
- * @{
- */
-/** @file
- * Standard control request handlers.
- */
 #include "private.h"
 #include <usb/request.h>
@@ -38,15 +4,4 @@
 #include <errno.h>
 
-/** Helper for replying to control read transfer from virtual USB device.
- *
- * This function takes care of copying data to answer buffer taking care
- * of buffer sizes properly.
- *
- * @param setup_packet The setup packet.
- * @param data Data buffer to write to.
- * @param act_size Where to write actual size of returned data.
- * @param actual_data Data to be returned.
- * @param actual_data_size Size of answer data (@p actual_data) in bytes.
- */
 void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet,
     uint8_t *data, size_t *act_size,
@@ -189,5 +144,4 @@
 }
 
-/** Standard request handlers. */
 usbvirt_control_request_handler_t library_handlers[] = {
 	{
@@ -219,5 +173,2 @@
 };
 
-/**
- * @}
- */
Index: uspace/lib/usbvirt/src/transfer.c
===================================================================
--- uspace/lib/usbvirt/src/transfer.c	(revision 7ab7c7f682acb2b85b576ebffa9c394b68bd0feb)
+++ uspace/lib/usbvirt/src/transfer.c	(revision 5d07f54c4e92772bedf67c509e44c68f45216eea)
@@ -31,5 +31,5 @@
  */
 /** @file
- * Transfer handling.
+ *
  */
 #include <usbvirt/device.h>
@@ -39,15 +39,4 @@
 #include "private.h"
 
-/** Process a control transfer to the virtual USB device.
- *
- * @param dev Target device.
- * @param setup Setup packet data.
- * @param setup_size Size of setup packet.
- * @param data Extra data (DATA stage).
- * @param data_size Size of extra data in bytes.
- * @param data_size_sent Number of actually send bytes during the transfer
- *	(only used for READ transfers).
- * @return Error code.
- */
 static int usbvirt_control_transfer(usbvirt_device_t *dev,
     void *setup, size_t setup_size,
@@ -89,15 +78,4 @@
 }
 
-/** Issue a control write transfer to virtual USB device.
- *
- * @see usbvirt_control_transfer
- *
- * @param dev Target virtual device.
- * @param setup Setup data.
- * @param setup_size Size of setup packet.
- * @param data Extra data (DATA stage).
- * @param data_size Size of extra data buffer in bytes.
- * @return Error code.
- */
 int usbvirt_control_write(usbvirt_device_t *dev, void *setup, size_t setup_size,
     void *data, size_t data_size)
@@ -107,16 +85,4 @@
 }
 
-/** Issue a control read transfer to virtual USB device.
- *
- * @see usbvirt_control_transfer
- *
- * @param dev Target virtual device.
- * @param setup Setup data.
- * @param setup_size Size of setup packet.
- * @param data Extra data (DATA stage).
- * @param data_size Size of extra data buffer in bytes.
- * @param data_size_sent Number of actually send bytes during the transfer.
- * @return Error code.
- */
 int usbvirt_control_read(usbvirt_device_t *dev, void *setup, size_t setup_size,
     void *data, size_t data_size, size_t *data_size_sent)
@@ -126,13 +92,4 @@
 }
 
-/** Send data to virtual USB device.
- *
- * @param dev Target virtual device.
- * @param transf_type Transfer type (interrupt, bulk).
- * @param endpoint Endpoint number.
- * @param data Data sent from the driver to the device.
- * @param data_size Size of the @p data buffer in bytes.
- * @return Error code.
- */
 int usbvirt_data_out(usbvirt_device_t *dev, usb_transfer_type_t transf_type,
     usb_endpoint_t endpoint, void *data, size_t data_size)
@@ -151,14 +108,4 @@
 }
 
-/** Request data from virtual USB device.
- *
- * @param dev Target virtual device.
- * @param transf_type Transfer type (interrupt, bulk).
- * @param endpoint Endpoint number.
- * @param data Where to stored data the device returns to the driver.
- * @param data_size Size of the @p data buffer in bytes.
- * @param data_size_sent Number of actually written bytes.
- * @return Error code.
- */
 int usbvirt_data_in(usbvirt_device_t *dev, usb_transfer_type_t transf_type,
     usb_endpoint_t endpoint, void *data, size_t data_size, size_t *data_size_sent)
