Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision c0e1be7d7b843208f87d11b9ec15b42235037122)
+++ uspace/lib/usb/Makefile	(revision b3718443703dd0cd113ce025bb4884a81207993a)
@@ -31,5 +31,6 @@
 
 SOURCES = \
-	hcd.c
+	hcd.c \
+	virtdev.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/hcd.h
===================================================================
--- uspace/lib/usb/hcd.h	(revision c0e1be7d7b843208f87d11b9ec15b42235037122)
+++ uspace/lib/usb/hcd.h	(revision b3718443703dd0cd113ce025bb4884a81207993a)
@@ -75,4 +75,10 @@
 	usb_endpoint_t endpoint;
 } usb_target_t;
+
+static inline int usb_target_same(usb_target_t a, usb_target_t b)
+{
+	return (a.address == b.address)
+	    && (a.endpoint == b.endpoint);
+}
 
 /** Opaque handle of active USB transaction.
Index: uspace/lib/usb/virtdev.c
===================================================================
--- uspace/lib/usb/virtdev.c	(revision b3718443703dd0cd113ce025bb4884a81207993a)
+++ uspace/lib/usb/virtdev.c	(revision b3718443703dd0cd113ce025bb4884a81207993a)
@@ -0,0 +1,178 @@
+/*
+ * 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 libusb usb
+ * @{
+ */
+/** @file
+ * @brief Virtual USB device (implementation).
+ */
+#include "virtdev.h"
+#include <devmap.h>
+#include <fcntl.h>
+#include <vfs/vfs.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#define NAMESPACE "usb"
+
+static usb_virtdev_on_data_from_host_t on_data_from_host = NULL;
+
+static void handle_data_to_device(ipc_callid_t iid, ipc_call_t icall)
+{
+	usb_endpoint_t endpoint = IPC_GET_ARG1(icall);
+	
+	size_t len;
+	void * buffer;
+	int rc = async_data_write_accept(&buffer, false,
+	    1, USB_MAX_PAYLOAD_SIZE,
+	    0, &len);
+	
+	if (rc != EOK) {
+		ipc_answer_0(iid, rc);
+		return;
+	}
+	
+	on_data_from_host(endpoint, buffer, len);
+	
+	free(buffer);
+	
+	ipc_answer_0(iid, EOK);
+}
+
+static void callback_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_callid_t callid; 
+		ipc_call_t call; 
+		
+		callid = async_get_call(&call);
+		switch (IPC_GET_METHOD(call)) {
+			case IPC_M_PHONE_HUNGUP:
+				ipc_answer_0(callid, EOK);
+				return;
+			
+			case IPC_M_USB_VIRTDEV_DATA_TO_DEVICE:
+				handle_data_to_device(callid, call);
+				break;
+			
+			default:
+				ipc_answer_0(callid, EINVAL);
+				break;
+		}
+	}
+}
+
+/** Create necessary phones for comunication with virtual HCD.
+ * This function wraps following calls:
+ * -# open <code>/dev/usb/<i>hcd_path</i></code> for reading
+ * -# access phone of file opened in previous step
+ * -# create callback through just opened phone
+ * -# create handler for calling on data from host to function
+ * -# return the (outgoing) phone
+ *
+ * @warning This function is wrapper for several actions and therefore
+ * it is not possible - in case of error - to determine at which point
+ * error occured.
+ *
+ * @param hcd_path HCD identification under devfs
+ *     (without <code>/dev/usb/</code>).
+ * @param device_id Internal device identification (used by HCD).
+ * @param callback Handler for callbacks from HCD.
+ * @return Phone for comunicating with HCD or error code from errno.h.
+ */
+int usb_virtdev_connect(const char *hcd_path, int device_id,
+    usb_virtdev_on_data_from_host_t callback)
+{
+	char dev_path[DEVMAP_NAME_MAXLEN + 1];
+	snprintf(dev_path, DEVMAP_NAME_MAXLEN,
+	    "/dev/%s/%s", NAMESPACE, hcd_path);
+	
+	int fd = open(dev_path, O_RDONLY);
+	if (fd < 0) {
+		return fd;
+	}
+	
+	int hcd_phone = fd_phone(fd);
+	
+	if (hcd_phone < 0) {
+		return hcd_phone;
+	}
+	
+	ipcarg_t phonehash;
+	int rc = ipc_connect_to_me(hcd_phone, 1, device_id, 0, &phonehash);
+	if (rc != EOK) {
+		return rc;
+	}
+	on_data_from_host = callback;
+	async_new_connection(phonehash, 0, NULL, callback_connection);
+	
+	return hcd_phone;
+}
+
+int usb_virtdev_data_to_host(int phone,
+    usb_endpoint_t endpoint,
+    void * buffer, size_t size)
+{
+	if (phone < 0) {
+		return EINVAL;
+	}
+	if ((buffer == NULL) || (size == 0)) {
+		return EINVAL;
+	}
+
+	ipc_call_t answer_data;
+	ipcarg_t answer_rc;
+	aid_t req;
+	int rc;
+	
+	req = async_send_1(phone,
+	    IPC_M_USB_VIRTDEV_DATA_FROM_DEVICE,
+	    endpoint,
+	    &answer_data);
+	
+	rc = async_data_write_start(phone, buffer, size);
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+	
+	async_wait_for(req, &answer_rc);
+	rc = (int)answer_rc;
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/virtdev.h
===================================================================
--- uspace/lib/usb/virtdev.h	(revision b3718443703dd0cd113ce025bb4884a81207993a)
+++ uspace/lib/usb/virtdev.h	(revision b3718443703dd0cd113ce025bb4884a81207993a)
@@ -0,0 +1,59 @@
+/*
+ * 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 libusb usb
+ * @{
+ */
+/** @file
+ * @brief Virtual USB device.
+ */
+#ifndef LIBUSB_VIRTDEV_H_
+#define LIBUSB_VIRTDEV_H_
+
+#include <ipc/ipc.h>
+#include <async.h>
+#include "hcd.h"
+
+#define USB_VIRTDEV_KEYBOARD_ID 1
+#define USB_VIRTDEV_KEYBOARD_ADDRESS 1
+
+typedef void (*usb_virtdev_on_data_from_host_t)(usb_endpoint_t, void *, size_t);
+
+int usb_virtdev_connect(const char *, int, usb_virtdev_on_data_from_host_t);
+int usb_virtdev_data_to_host(int, usb_endpoint_t,
+    void *, size_t);
+
+typedef enum {
+	IPC_M_USB_VIRTDEV_DATA_TO_DEVICE = IPC_FIRST_USER_METHOD,
+	IPC_M_USB_VIRTDEV_DATA_FROM_DEVICE
+} usb_virtdev_method_t;
+
+#endif
+/**
+ * @}
+ */
