Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/Makefile	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -51,5 +51,4 @@
 	app/top \
 	app/usbinfo \
-	app/virtusbkbd \
 	app/vuhid \
 	app/netecho \
Index: uspace/app/virtusbkbd/Makefile
===================================================================
--- uspace/app/virtusbkbd/Makefile	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,43 +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.
-#
-
-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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,51 +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 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(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/virtusbkbd/kbdconfig.c
===================================================================
--- uspace/app/virtusbkbd/kbdconfig.c	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,155 +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 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,60 +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 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,123 +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 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,121 +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 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(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/virtusbkbd/stdreq.c
===================================================================
--- uspace/app/virtusbkbd/stdreq.c	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,64 +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 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,47 +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 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,267 +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 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/app/vuhid/device.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -77,8 +77,14 @@
 {
 	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;
@@ -110,4 +116,11 @@
 	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;
 	}
 
@@ -252,4 +265,5 @@
 
 	/* Launch the "life" fibril. */
+	iface->vuhid_data = hid_data;
 	fid_t life_fibril = fibril_create(interface_life_fibril, iface);
 	if (life_fibril == 0) {
@@ -310,4 +324,5 @@
 	    += total_descr_size;
 
+	hid_data->iface_count++;
 	fibril_add_ready(life_fibril);
 
@@ -331,4 +346,15 @@
 }
 
+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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/app/vuhid/hids/bootkbd.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -39,5 +39,5 @@
 #include <usb/classes/hidut.h>
 
-#include "../../virtusbkbd/report.h"
+#include "../report.h"
 
 uint8_t report_descriptor[] = {
@@ -169,5 +169,7 @@
 	.on_data_out = on_data_out,
 
-	.live = live
+	.live = live,
+
+	.vuhid_data = NULL
 };
 
Index: uspace/app/vuhid/items.h
===================================================================
--- uspace/app/vuhid/items.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
+++ uspace/app/vuhid/items.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -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/vuhid/main.c
===================================================================
--- uspace/app/vuhid/main.c	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/app/vuhid/main.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -132,6 +132,11 @@
 	.in_endpoint_first_free = 1,
 	.out_endpoints_mapping = { NULL },
-	.out_endpoint_first_free = 1
-};
+	.out_endpoint_first_free = 1,
+
+	.iface_count = 0,
+	.iface_died_count = 0
+	// mutex and CV must be initialized elsewhere
+};
+
 
 /** Keyboard device.
@@ -151,4 +156,7 @@
 
 	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. */
@@ -182,10 +190,10 @@
 	printf("Connected to VHCD...\n");
 
-	while (true) {
-		async_usleep(10 * 1000 * 1000);
-	}
+	wait_for_interfaces_death(&hid_dev);
 	
 	printf("Terminating...\n");
 	
+	usbvirt_device_unplug(&hid_dev);
+
 	return 0;
 }
Index: uspace/app/vuhid/report.h
===================================================================
--- uspace/app/vuhid/report.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
+++ uspace/app/vuhid/report.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -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/vuhid/virthid.h
===================================================================
--- uspace/app/vuhid/virthid.h	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/app/vuhid/virthid.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -38,4 +38,5 @@
 #include <usb/usb.h>
 #include <usbvirt/device.h>
+#include <fibril_synch.h>
 
 #define VUHID_ENDPOINT_MAX USB11_ENDPOINT_MAX
@@ -43,4 +44,17 @@
 
 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 {
@@ -63,13 +77,7 @@
 
 	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 {
@@ -84,4 +92,5 @@
 
 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/vhc/transfer.c
===================================================================
--- uspace/drv/vhc/transfer.c	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/drv/vhc/transfer.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -135,5 +135,4 @@
 		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,
@@ -142,5 +141,4 @@
 			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/usbvirt/Makefile
===================================================================
--- uspace/lib/usbvirt/Makefile	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/lib/usbvirt/Makefile	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -33,6 +33,8 @@
 
 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/lib/usbvirt/include/usbvirt/device.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Virtual USB device.
+ * Virtual USB device.
  */
 #ifndef LIBUSBVIRT_DEVICE_H_
@@ -39,21 +39,68 @@
 #include <usb/request.h>
 
+/** Maximum number of endpoints supported by virtual USB. */
 #define USBVIRT_ENDPOINT_MAX 16
 
 typedef struct usbvirt_device usbvirt_device_t;
 
-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 *);
-
-typedef struct {
+/** 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);
+
+/** 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;
@@ -77,5 +124,5 @@
 } usbvirt_device_configuration_t;
 
-/** Standard USB descriptors. */
+/** Standard USB descriptors for virtual device. */
 typedef struct {
 	/** Standard device descriptor.
@@ -102,22 +149,57 @@
 } usbvirt_device_state_t;
 
-typedef struct {
+/** 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/lib/usbvirt/include/usbvirt/ipc.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Vojtech Horky
  * All rights reserved.
  *
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Virtual USB device.
+ * IPC wrappers for virtual USB.
  */
 #ifndef LIBUSBVIRT_IPC_H_
@@ -40,4 +40,5 @@
 #include <bool.h>
 
+/** IPC methods communication between host controller and virtual device. */
 typedef enum {
 	IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD + 80,
@@ -45,10 +46,12 @@
 	IPC_M_USBVIRT_CONTROL_WRITE,
 	IPC_M_USBVIRT_INTERRUPT_IN,
-	IPC_M_USBVIRT_INTERRUPT_OUT
-} usbvirt_ipc_t;
+	IPC_M_USBVIRT_INTERRUPT_OUT,
+	IPC_M_USBVIRT_BULK_IN,
+	IPC_M_USBVIRT_BULK_OUT
+} usbvirt_hc_to_device_method_t;
 
-int usbvirt_ipc_send_control_read(int, usb_endpoint_t, void *, size_t,
+int usbvirt_ipc_send_control_read(int, void *, size_t,
     void *, size_t, size_t *);
-int usbvirt_ipc_send_control_write(int, usb_endpoint_t, void *, size_t,
+int usbvirt_ipc_send_control_write(int, 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/lib/usbvirt/src/ctrltransfer.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -1,2 +1,36 @@
+/*
+ * 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>
@@ -5,4 +39,14 @@
 #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,
@@ -52,2 +96,7 @@
 	return EFORWARD;
 }
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/device.c
===================================================================
--- uspace/lib/usbvirt/src/device.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
+++ uspace/lib/usbvirt/src/device.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -0,0 +1,127 @@
+/*
+ * 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ 	(revision )
@@ -1,455 +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
- *
- */
-#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: uspace/lib/usbvirt/src/ipc_dev.c
===================================================================
--- uspace/lib/usbvirt/src/ipc_dev.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
+++ uspace/lib/usbvirt/src/ipc_dev.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -0,0 +1,297 @@
+/*
+ * 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: uspace/lib/usbvirt/src/ipc_hc.c
===================================================================
--- uspace/lib/usbvirt/src/ipc_hc.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
+++ uspace/lib/usbvirt/src/ipc_hc.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -0,0 +1,298 @@
+/*
+ * 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 f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/lib/usbvirt/src/private.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -1,2 +1,39 @@
+/*
+ * 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>
 
@@ -7,2 +44,7 @@
 
 extern usbvirt_control_request_handler_t library_handlers[];
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/stdreq.c
===================================================================
--- uspace/lib/usbvirt/src/stdreq.c	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/lib/usbvirt/src/stdreq.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -1,2 +1,36 @@
+/*
+ * 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>
@@ -4,4 +38,15 @@
 #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,
@@ -144,4 +189,5 @@
 }
 
+/** Standard request handlers. */
 usbvirt_control_request_handler_t library_handlers[] = {
 	{
@@ -173,2 +219,5 @@
 };
 
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/transfer.c
===================================================================
--- uspace/lib/usbvirt/src/transfer.c	(revision f90c0d6c1710d4e0841deffb9389c9f882f27afd)
+++ uspace/lib/usbvirt/src/transfer.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -31,5 +31,5 @@
  */
 /** @file
- *
+ * Transfer handling.
  */
 #include <usbvirt/device.h>
@@ -39,4 +39,15 @@
 #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,
@@ -78,4 +89,15 @@
 }
 
+/** 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)
@@ -85,4 +107,16 @@
 }
 
+/** 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)
@@ -92,4 +126,13 @@
 }
 
+/** 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)
@@ -108,4 +151,14 @@
 }
 
+/** 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)
