Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 9a1d8abd4768c007dc2f27c914e04be26e5a64f5)
+++ uspace/Makefile	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -71,4 +71,5 @@
 	srv/hw/char/s3c24xx_uart \
 	srv/hw/netif/dp8390 \
+	srv/hw/bus/usb/hcd/virtual \
 	srv/net/cfg \
 	srv/net/netif/lo \
@@ -80,4 +81,5 @@
 	srv/net/net \
 	srv/net/netstart \
+	app/usb \
 	app/netecho \
 	app/nettest1 \
@@ -138,8 +140,10 @@
 ifeq ($(UARCH),amd64)
 	LIBS += lib/pci
+	LIBS += lib/usb
 endif
 
 ifeq ($(UARCH),ia32)
 	LIBS += lib/pci
+	LIBS += lib/usb
 endif
 
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 9a1d8abd4768c007dc2f27c914e04be26e5a64f5)
+++ uspace/Makefile.common	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -87,4 +87,5 @@
 
 LIBPCI_PREFIX = $(LIB_PREFIX)/pci
+LIBUSB_PREFIX = $(LIB_PREFIX)/usb
 
 LIBSOCKET_PREFIX = $(LIB_PREFIX)/socket
Index: uspace/app/usb/Makefile
===================================================================
--- uspace/app/usb/Makefile	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/app/usb/Makefile	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,36 @@
+#
+# 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 = ../..
+BINARY = usb
+LIBS = $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS = -I$(LIB_PREFIX)
+SOURCES = \
+	example.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/usb/example.c
===================================================================
--- uspace/app/usb/example.c	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/app/usb/example.c	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,173 @@
+/*
+ * 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 usb
+ * @{
+ */
+/**
+ * @file
+ * @brief Simple application that connects to USB/HCD.
+ */
+
+#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/hcd.h>
+
+#define LOOPS 5
+#define MAX_SIZE_RECEIVE 64
+#define NAME "hcd-example"
+
+#define DEV_HCD_NAME "hcd-virt"
+
+#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__))
+
+static void fibril_sleep(size_t sec)
+{
+	while (sec-- > 0) {
+		async_usleep(1000*1000);
+	}
+}
+
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_answer_0(iid, EOK);
+	printf("%s: client connection()\n", NAME);
+	
+	while (true) {
+		ipc_callid_t callid; 
+		ipc_call_t call; 
+		int rc;
+		void * buffer;
+		size_t len;
+		
+		callid = async_get_call(&call);
+		
+		switch (IPC_GET_METHOD(call)) {
+			case IPC_M_USB_HCD_DATA_SENT:
+				printf("%s: >> Data sent over USB (handle %d, outcome %s).\n",
+				    NAME, IPC_GET_ARG1(call),
+				    usb_str_transaction_outcome(IPC_GET_ARG2(call)));
+				ipc_answer_0(callid, EOK);
+				break;
+			case IPC_M_USB_HCD_DATA_RECEIVED:
+				printf("%s: << Data received over USB (handle %d, outcome %s).\n",
+				    NAME, IPC_GET_ARG1(call),
+				    usb_str_transaction_outcome(IPC_GET_ARG2(call)));
+				if (IPC_GET_ARG2(call) != USB_OUTCOME_OK) {
+					ipc_answer_0(callid, EOK);
+					break;
+				}
+				rc = async_data_write_accept(&buffer, false,
+				    1, MAX_SIZE_RECEIVE,
+				    0, &len);
+				if (rc != EOK) {
+					ipc_answer_0(callid, rc);
+					break;
+				}
+				printf("%s: << Received %uB long buffer (handle %d).\n",
+				    NAME, len, IPC_GET_ARG1(call));
+				ipc_answer_0(callid, EOK);
+				break;
+			default:
+				ipc_answer_0(callid, EINVAL);
+				break;
+		}
+	}
+}
+
+int main(int argc, char * argv[])
+{
+	int hcd_phone = usb_hcd_create_phones(DEV_HCD_NAME, client_connection);
+	if (hcd_phone < 0) {
+		printf("%s: Unable to start comunication with HCD at usb://%s (%d: %s).\n",
+		    NAME, DEV_HCD_NAME, hcd_phone, str_error(hcd_phone));
+		return 1;
+	}
+	
+	char data[] = "Hullo, World!";
+	int data_len = sizeof(data)/sizeof(data[0]);
+	
+	size_t i;
+	for (i = 0; i < LOOPS; i++) {
+		usb_transaction_handle_t handle;
+
+		usb_target_t target = { 11 + i, 3 };
+		int rc = usb_hcd_send_data_to_function(hcd_phone,
+		    target, USB_TRANSFER_ISOCHRONOUS,
+		    data, data_len,
+		    &handle);
+		if (rc != EOK) {
+			printf("%s: >> Failed to send data to function over HCD (%d: %s).\n",
+				NAME, rc, str_error(rc));
+			continue;
+		}
+
+		printf("%s: >> Transaction to function dispatched (handle %d).\n", NAME, handle);
+		
+		fibril_sleep(1);
+		
+		rc = usb_hcd_prepare_data_reception(hcd_phone,
+		    target, USB_TRANSFER_INTERRUPT,
+		    MAX_SIZE_RECEIVE,
+		    &handle);
+		if (rc != EOK) {
+			printf("%s: << Failed to start transaction for data receivement over HCD (%d: %s).\n",
+				NAME, rc, str_error(rc));
+			continue;
+		}
+		
+		printf("%s: << Transaction from function started (handle %d).\n", NAME, handle);
+		
+		fibril_sleep(2);
+	}
+	
+	printf("%s: Waiting for transactions to be finished...\n", NAME);
+	fibril_sleep(10);
+	
+	printf("%s: exiting.\n", NAME);
+	
+	ipc_hangup(hcd_phone);
+	
+	return 0;
+}
+
+
+/** @}
+ */
Index: uspace/doc/doxygroups.h
===================================================================
--- uspace/doc/doxygroups.h	(revision 9a1d8abd4768c007dc2f27c914e04be26e5a64f5)
+++ uspace/doc/doxygroups.h	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -155,5 +155,5 @@
 	 * @endcond
 	 */
-	
+
 /**
  * @defgroup emul Emulation Libraries
@@ -170,2 +170,13 @@
 	 * @ingroup emul
 	 */
+
+/**
+ * @defgroup usb USB
+ * @ingroup uspace
+ * @brief USB support for HelenOS.
+ */
+	/**
+	 * @defgroup libusb USB library
+	 * @ingroup usb
+	 * @brief Library for creating USB devices drivers.
+	 */
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/lib/usb/Makefile	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,35 @@
+#
+# 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 = ../..
+LIBRARY = libusb
+
+SOURCES = \
+	hcd.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/hcd.c
===================================================================
--- uspace/lib/usb/hcd.c	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/lib/usb/hcd.c	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,215 @@
+/*
+ * 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 USB Host Controller Driver (implementation).
+ */
+#include "hcd.h"
+#include <devmap.h>
+#include <fcntl.h>
+#include <vfs/vfs.h>
+#include <errno.h>
+
+
+#define NAMESPACE "usb"
+
+/** String representation for USB transfer type. */
+const char * usb_str_transfer_type(usb_transfer_type_t t)
+{
+	switch (t) {
+		case USB_TRANSFER_ISOCHRONOUS:
+			return "isochronous";
+		case USB_TRANSFER_INTERRUPT:
+			return "interrupt";
+		case USB_TRANSFER_CONTROL:
+			return "control";
+		case USB_TRANSFER_BULK:
+			return "bulk";
+		default:
+			return "unknown";
+	}
+}
+
+/** String representation of USB transaction outcome. */
+const char * usb_str_transaction_outcome(usb_transaction_outcome_t o)
+{
+	switch (o) {
+		case USB_OUTCOME_OK:
+			return "ok";
+		case USB_OUTCOME_CRCERROR:
+			return "CRC error";
+		case USB_OUTCOME_BABBLE:
+			return "babble";
+		default:
+			return "unknown";
+	}
+}
+
+/** Create necessary phones for comunicating with 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
+ * -# set handler for this callback
+ * -# 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 callback_connection Handler for callbacks from HCD.
+ * @return Phone for comunicating with HCD or error code from errno.h.
+ */
+int usb_hcd_create_phones(const char * hcd_path,
+    async_client_conn_t callback_connection)
+{
+	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, 0, 0, 0, &phonehash);
+	if (rc != EOK) {
+		return rc;
+	}
+	async_new_connection(phonehash, 0, NULL, callback_connection);
+	
+	return hcd_phone;
+}
+
+/** Send data from USB host to a function.
+ *
+ * @param hcd_phone Connected phone to HCD.
+ * @param target USB function address.
+ * @param transfer_type USB transfer type.
+ * @param buffer Buffer with data to be sent.
+ * @param len Buffer @p buffer size.
+ * @param[out] transaction_handle Handle of created transaction (NULL to ignore).
+ * @return Error status.
+ * @retval EOK Everything OK, buffer transfered to HCD and queued there.
+ * @retval EINVAL Invalid phone.
+ * @retval EINVAL @p buffer is NULL.
+ */
+int usb_hcd_send_data_to_function(int hcd_phone,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    void * buffer, size_t len,
+    usb_transaction_handle_t * transaction_handle)
+{
+	if (hcd_phone < 0) {
+		return EINVAL;
+	}
+	if (buffer == NULL) {
+		return EINVAL;
+	}
+
+	ipc_call_t answer_data;
+	ipcarg_t answer_rc;
+	aid_t req;
+	int rc;
+	
+	req = async_send_4(hcd_phone,
+	    IPC_M_USB_HCD_SEND_DATA,
+	    target.address, target.endpoint,
+	    transfer_type, 0,
+	    &answer_data);
+	
+	rc = async_data_write_start(hcd_phone, buffer, len);
+	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;
+	}
+	
+	if (transaction_handle != NULL) {
+		*transaction_handle = IPC_GET_ARG1(answer_data);
+	}
+	
+	return EOK;
+}
+
+
+/** Inform HCD about data reception.
+ * The actual reception is handled in callback.
+ *
+ * @param hcd_phone Connected phone to HCD.
+ * @param target USB function address.
+ * @param transfer_type USB transfer type.
+ * @param len Maximum accepted packet size.
+ * @param[out] transaction_handle Handle of created transaction (NULL to ignore).
+ * @return Error status.
+ */
+int usb_hcd_prepare_data_reception(int hcd_phone,
+    usb_target_t target, usb_transfer_type_t transfer_type,
+    size_t len,
+    usb_transaction_handle_t * transaction_handle)
+{
+	if (hcd_phone < 0) {
+		return EINVAL;
+	}
+	
+	usb_transaction_handle_t handle;
+	
+	int rc = ipc_call_sync_5_1(hcd_phone, IPC_M_USB_HCD_RECEIVE_DATA,
+	    target.address, target.endpoint,
+	    transfer_type, len, 0, &handle);
+	
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	if (transaction_handle != NULL) {
+		*transaction_handle = handle;
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/hcd.h
===================================================================
--- uspace/lib/usb/hcd.h	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/lib/usb/hcd.h	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,190 @@
+/*
+ * 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 USB Host Controller Driver.
+ */
+#ifndef LIBUSB_HCD_H_
+#define LIBUSB_HCD_H_
+
+#include <ipc/ipc.h>
+#include <async.h>
+
+/** Maximum size of transaction payload. */
+#define USB_MAX_PAYLOAD_SIZE 1020
+
+/** USB transfer type. */
+typedef enum {
+	USB_TRANSFER_ISOCHRONOUS,
+	USB_TRANSFER_INTERRUPT,
+	USB_TRANSFER_CONTROL,
+	USB_TRANSFER_BULK
+} usb_transfer_type_t;
+
+const char * usb_str_transfer_type(usb_transfer_type_t t);
+
+/** USB data transfer direction. */
+typedef enum {
+	USB_DIRECTION_IN,
+	USB_DIRECTION_OUT
+} usb_direction_t;
+
+/** USB address type.
+ * Negative values could be used to indicate error.
+ */
+typedef int usb_address_t;
+
+/** USB endpoint number type.
+ * Negative values could be used to indicate error.
+ */
+typedef int usb_endpoint_t;
+
+/** USB complete address type. 
+ * Pair address + endpoint is identification of transaction recipient.
+ */
+typedef struct {
+	usb_address_t address;
+	usb_endpoint_t endpoint;
+} usb_target_t;
+
+/** Opaque handle of active USB transaction.
+ * This handle is when informing about transaction outcome (or status).
+ */
+typedef ipcarg_t usb_transaction_handle_t;
+
+/** USB transaction outcome. */
+typedef enum {
+	USB_OUTCOME_OK,
+	USB_OUTCOME_CRCERROR,
+	USB_OUTCOME_BABBLE
+} usb_transaction_outcome_t;
+
+const char * usb_str_transaction_outcome(usb_transaction_outcome_t o);
+
+/** IPC methods for HCD. */
+typedef enum {
+	/** Send data over USB to a function.
+	 * This method initializes large data transfer that must follow
+	 * immediatelly.
+	 * The recipient of this method must issue immediately data reception
+	 * and answer this call after data buffer was transfered.
+	 * 
+	 * Arguments of the call:
+	 * - USB address of the function
+	 * - endpoint of the function
+	 * - transfer type
+	 * - flags (not used)
+	 * 
+	 * Answer:
+	 * - EOK - ready to accept the data buffer
+	 * - ELIMIT - too many transactions for current connection
+	 * - ENOENT - callback connection does not exist
+	 * - EINVAL - other kind of error
+	 * 
+	 * Arguments of the answer:
+	 * - opaque transaction handle (used in callbacks)
+	 */
+	IPC_M_USB_HCD_SEND_DATA = IPC_FIRST_USER_METHOD,
+	
+	/** Initiate data receive from a function.
+	 * This method announces the HCD that some data will come.
+	 * When this data arrives, the HCD will call back with
+	 * IPC_M_USB_HCD_DATA_RECEIVED.
+	 * 
+	 * Arguments of the call:
+	 * - USB address of the function
+	 * - endpoint of the function
+	 * - transfer type
+	 * - buffer size
+	 * - flags (not used)
+	 *
+	 * Answer:
+	 * - EOK - HCD accepted the request
+	 * - ELIMIT - too many transactions for current connection
+	 * - ENOENT - callback connection does not exist
+	 *
+	 * Arguments of the answer:
+	 * - opaque transaction handle (used in callbacks)
+	 */
+	IPC_M_USB_HCD_RECEIVE_DATA,
+	
+	/** Tell maximum size of the transaction buffer (payload).
+	 * 
+	 * Arguments of the call:
+	 *  (none)
+	 * 
+	 * Answer:
+	 * - EOK - always
+	 * 
+	 * Arguments of the answer:
+	 * - buffer size (in bytes):
+	 */
+	IPC_M_USB_HCD_TRANSACTION_SIZE
+} usb_hcd_method_t;
+
+/** IPC methods for callbacks from HCD. */
+typedef enum {
+	/** Confimation after data sent.
+	 * 
+	 * Arguments of the call:
+	 * - transaction handle
+	 * - transaction outcome
+	 */
+	IPC_M_USB_HCD_DATA_SENT = IPC_FIRST_USER_METHOD,
+	
+	/** Notification of data received.
+	 * This call initiates sending a data buffer from HCD to the client.
+	 * See IPC_M_USB_HCD_SEND_DATA for details for buffer transfer is
+	 * done.
+	 * 
+	 * Arguments of the call:
+	 * - transaction handle
+	 * - transaction outcome
+	 * - actual data length
+	 */
+	IPC_M_USB_HCD_DATA_RECEIVED,
+	
+	/** Notification about a serious trouble with HC.
+	 */
+	IPC_M_USB_HCD_CONTROLLER_FAILURE
+} usb_hcd_callback_method_t;
+
+
+int usb_hcd_create_phones(const char *, async_client_conn_t);
+int usb_hcd_send_data_to_function(int, usb_target_t, usb_transfer_type_t,
+    void *, size_t, usb_transaction_handle_t *);
+int usb_hcd_prepare_data_reception(int, usb_target_t, usb_transfer_type_t,
+    size_t, usb_transaction_handle_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/srv/hw/bus/usb/hcd/virtual/Makefile
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/Makefile	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/srv/hw/bus/usb/hcd/virtual/Makefile	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,38 @@
+#
+# 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 = ../../../../../..
+LIBS = $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS = -I$(LIB_PREFIX)
+BINARY = vhcd
+
+SOURCES = \
+	hc.c \
+	hcd.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hw/bus/usb/hcd/virtual/hc.c
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/hc.c	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/srv/hw/bus/usb/hcd/virtual/hc.c	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,195 @@
+/*
+ * 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 usb
+ * @{
+ */
+/** @file
+ * @brief Virtual HC (implementation).
+ */
+
+#include <ipc/ipc.h>
+#include <adt/list.h>
+#include <bool.h>
+#include <async.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "vhcd.h"
+#include "hc.h"
+
+#define USLEEP_BASE (500 * 1000)
+
+#define USLEEP_VAR 10000
+
+#define SHORTENING_VAR 15
+
+#define PROB_OUTCOME_BABBLE 5
+#define PROB_OUTCOME_CRCERROR 7
+
+#define PROB_TEST(var, new_value, prob, number) \
+	do { \
+		if (((number) % (prob)) == 0) { \
+			var = (new_value); \
+		} \
+	} while (0)
+
+static link_t transaction_list;
+
+
+typedef struct {
+	link_t link;
+	usb_target_t target;
+	usb_direction_t direction;
+	usb_transfer_type_t type;
+	void * buffer;
+	size_t len;
+	hc_transaction_done_callback_t callback;
+	void * callback_arg;
+} transaction_t;
+
+#define TRANSACTION_FORMAT "T[%d:%d %s %s (%d)]"
+#define TRANSACTION_PRINTF(t) \
+	(t).target.address, (t).target.endpoint, \
+	usb_str_transfer_type((t).type), \
+	((t).direction == USB_DIRECTION_IN ? "in" : "out"), \
+	(int)(t).len
+
+#define transaction_get_instance(lnk) \
+	list_get_instance(lnk, transaction_t, link)
+
+static inline unsigned int pseudo_random(unsigned int *seed)
+{
+	*seed = ((*seed) * 873511) % 22348977 + 7;
+	return ((*seed) >> 8);
+}
+
+static void process_transaction_with_outcome(transaction_t * transaction,
+    usb_transaction_outcome_t outcome)
+{
+	dprintf("processing transaction " TRANSACTION_FORMAT ", outcome: %s",
+	    TRANSACTION_PRINTF(*transaction),
+	    usb_str_transaction_outcome(outcome));
+	
+	transaction->callback(transaction->buffer, transaction->len, outcome,
+	    transaction->callback_arg);
+}
+
+static void process_transaction(transaction_t * transaction)
+{
+	static unsigned int seed = 4089;
+	
+	unsigned int roulette = pseudo_random(&seed);
+	usb_transaction_outcome_t outcome = USB_OUTCOME_OK;
+	
+	PROB_TEST(outcome, USB_OUTCOME_BABBLE, PROB_OUTCOME_BABBLE, roulette);
+	PROB_TEST(outcome, USB_OUTCOME_CRCERROR, PROB_OUTCOME_CRCERROR, roulette);
+	
+	process_transaction_with_outcome(transaction, outcome);
+}
+
+void hc_manager(void)
+{
+	list_initialize(&transaction_list);
+	
+	static unsigned int seed = 4573;
+	
+	printf("%s: transaction processor ready.\n", NAME);
+	
+	while (true) {
+		async_usleep(USLEEP_BASE + (pseudo_random(&seed) % USLEEP_VAR));
+		
+		if (list_empty(&transaction_list)) {
+			continue;
+		}
+		
+		link_t * first_transaction_link = transaction_list.next;
+		transaction_t * first_transaction
+		    = transaction_get_instance(first_transaction_link);
+		list_remove(first_transaction_link);
+		
+		process_transaction(first_transaction);
+		
+		free(first_transaction);
+	}
+}
+
+static void hc_add_transaction(usb_transfer_type_t type, usb_target_t target,
+    usb_direction_t direction,
+    void * buffer, size_t len,
+    hc_transaction_done_callback_t callback, void * arg)
+{
+	transaction_t * transaction = malloc(sizeof(transaction_t));
+	
+	list_initialize(&transaction->link);
+	transaction->type = type;
+	transaction->target = target;
+	transaction->direction = direction;
+	transaction->buffer = buffer;
+	transaction->len = len;
+	transaction->callback = callback;
+	transaction->callback_arg = arg;
+	
+	dprintf("adding transaction " TRANSACTION_FORMAT,
+	    TRANSACTION_PRINTF(*transaction));
+
+	list_append(&transaction->link, &transaction_list);
+}
+
+void hc_add_out_transaction(usb_transfer_type_t type, usb_target_t target,
+    void * buffer, size_t len,
+    hc_transaction_done_callback_t callback, void * arg)
+{
+	hc_add_transaction(type, target, USB_DIRECTION_OUT,
+	    buffer, len, callback, arg);
+}
+
+void hc_add_in_transaction(usb_transfer_type_t type, usb_target_t target,
+    void * buffer, size_t len,
+    hc_transaction_done_callback_t callback, void * arg)
+{
+	static unsigned int seed = 216;
+	
+	size_t i;
+	char * data = (char *)buffer;
+	for (i = 0; i < len; i++, data++) {
+		*data = 'A' + (pseudo_random(&seed) % ('Z' - 'A'));
+	}
+	
+	unsigned int shortening = pseudo_random(&seed) % SHORTENING_VAR;
+	if (len > shortening) {
+		len -= shortening;
+	}
+	
+	hc_add_transaction(type, target, USB_DIRECTION_IN,
+	    buffer, len, callback, arg);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hw/bus/usb/hcd/virtual/hc.h
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/hc.h	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/srv/hw/bus/usb/hcd/virtual/hc.h	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,56 @@
+/*
+ * 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 usb
+ * @{
+ */
+/** @file
+ * @brief Virtual HC.
+ */
+#ifndef VHCD_HC_H_
+#define VHCD_HC_H_
+
+#include <usb/hcd.h>
+
+typedef void (*hc_transaction_done_callback_t)(void *, size_t, usb_transaction_outcome_t, void *);
+
+void hc_manager(void);
+
+void hc_add_out_transaction(usb_transfer_type_t type, usb_target_t target,
+    void * buffer, size_t len,
+    hc_transaction_done_callback_t callback, void * arg);
+
+void hc_add_in_transaction(usb_transfer_type_t type, usb_target_t target,
+    void * buffer, size_t len,
+    hc_transaction_done_callback_t callback, void * arg);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/srv/hw/bus/usb/hcd/virtual/hcd.c
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/hcd.c	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/srv/hw/bus/usb/hcd/virtual/hcd.c	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,268 @@
+/*
+ * 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 usb
+ * @{
+ */ 
+/** @file
+ * @brief Virtual host controller driver.
+ */
+
+#include <devmap.h>
+#include <ipc/ipc.h>
+#include <async.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/hcd.h>
+#include "vhcd.h"
+#include "hc.h"
+
+static usb_transaction_handle_t g_handle_seed = 1;
+static usb_transaction_handle_t create_transaction_handle(int phone)
+{
+	return g_handle_seed++;
+}
+
+typedef struct {
+	int phone;
+	usb_transaction_handle_t handle;
+} transaction_details_t;
+
+static void out_callback(void * buffer, size_t len, usb_transaction_outcome_t outcome, void * arg)
+{
+	(void)len;
+	transaction_details_t * trans = (transaction_details_t *)arg;
+	
+	async_msg_2(trans->phone, IPC_M_USB_HCD_DATA_SENT, trans->handle, outcome);
+	
+	free(trans);
+	free(buffer);
+}
+
+static void in_callback(void * buffer, size_t len, usb_transaction_outcome_t outcome, void * arg)
+{
+	transaction_details_t * trans = (transaction_details_t *)arg;
+	
+	ipc_call_t answer_data;
+	ipcarg_t answer_rc;
+	aid_t req;
+	int rc;
+	
+	req = async_send_3(trans->phone,
+	    IPC_M_USB_HCD_DATA_RECEIVED,
+	    trans->handle, outcome,
+	    len,
+	    &answer_data);
+	
+	rc = async_data_write_start(trans->phone, buffer, len);
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		goto leave;
+	}
+	
+	async_wait_for(req, &answer_rc);
+	rc = (int)answer_rc;
+	if (rc != EOK) {
+		goto leave;
+	}
+	
+leave:
+	free(trans);
+	free(buffer);
+}
+
+
+
+static void handle_data_to_function(ipc_callid_t iid, ipc_call_t icall, int callback_phone)
+{
+	usb_transfer_type_t transf_type = IPC_GET_ARG3(icall);
+	usb_target_t target = {
+		.address = IPC_GET_ARG1(icall),
+		.endpoint = IPC_GET_ARG2(icall)
+	};
+	
+	dprintf("pretending transfer to function (dev=%d:%d, type=%s)",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transf_type));
+	
+	if (callback_phone == -1) {
+		ipc_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	usb_transaction_handle_t handle
+	    = create_transaction_handle(callback_phone);
+	
+	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;
+	}
+	
+	transaction_details_t * trans = malloc(sizeof(transaction_details_t));
+	trans->phone = callback_phone;
+	trans->handle = handle;
+	
+	dprintf("adding transaction to HC", NAME);
+	hc_add_out_transaction(transf_type, target,
+	    buffer, len,
+	    out_callback, trans);
+	
+	ipc_answer_1(iid, EOK, handle);
+	dprintf("transfer to function scheduled (handle %d)", handle);
+}
+
+static void handle_data_from_function(ipc_callid_t iid, ipc_call_t icall, int callback_phone)
+{
+	usb_transfer_type_t transf_type = IPC_GET_ARG3(icall);
+	usb_target_t target = {
+		.address = IPC_GET_ARG1(icall),
+		.endpoint = IPC_GET_ARG2(icall)
+	};
+	size_t len = IPC_GET_ARG4(icall);
+	
+	dprintf("pretending transfer from function (dev=%d:%d, type=%s)",
+	    target.address, target.endpoint,
+	    usb_str_transfer_type(transf_type));
+	
+	if (callback_phone == -1) {
+		ipc_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	usb_transaction_handle_t handle
+	    = create_transaction_handle(callback_phone);
+	
+	void * buffer = malloc(len);
+	
+	transaction_details_t * trans = malloc(sizeof(transaction_details_t));
+	trans->phone = callback_phone;
+	trans->handle = handle;
+	
+	dprintf("adding transaction to HC", NAME);
+	hc_add_in_transaction(transf_type, target,
+	    buffer, len,
+	    in_callback, trans);
+	
+	ipc_answer_1(iid, EOK, handle);
+	dprintf("transfer from function scheduled (handle %d)", handle);
+}
+
+
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipcarg_t phone_hash = icall->in_phone_hash;
+	
+	ipc_answer_0(iid, EOK);
+	printf("%s: new client connected (phone %#x).\n", NAME, phone_hash);
+	
+	int callback_phone = -1;
+	
+	while (true) {
+		ipc_callid_t callid; 
+		ipc_call_t call; 
+		
+		callid = async_get_call(&call);
+		dprintf("%#x calls method %d", phone_hash, IPC_GET_METHOD(call));
+		switch (IPC_GET_METHOD(call)) {
+			case IPC_M_PHONE_HUNGUP:
+				if (callback_phone != -1) {
+					ipc_hangup(callback_phone);
+				}
+				ipc_answer_0(callid, EOK);
+				printf("%s: hung-up on %#x.\n", NAME, phone_hash);
+				return;
+			
+			case IPC_M_CONNECT_TO_ME:
+				if (callback_phone != -1) {
+					ipc_answer_0(callid, ELIMIT);
+				} else {
+					callback_phone = IPC_GET_ARG5(call);
+					ipc_answer_0(callid, EOK);
+				}
+				break;
+			
+			case IPC_M_USB_HCD_SEND_DATA:
+				handle_data_to_function(callid, call, callback_phone);
+				break;
+			
+			case IPC_M_USB_HCD_RECEIVE_DATA:
+				handle_data_from_function(callid, call, callback_phone);
+				break;
+			
+			case IPC_M_USB_HCD_TRANSACTION_SIZE:
+				ipc_answer_1(callid, EOK, USB_MAX_PAYLOAD_SIZE);
+				break;
+			
+			default:
+				ipc_answer_0(callid, EINVAL);
+				break;
+		}
+	}
+}
+
+int main(int argc, char * argv[])
+{
+	printf("%s: Virtual USB host controller driver.\n", NAME);
+	
+	int rc;
+	
+	rc = devmap_driver_register(NAME, client_connection); 
+	if (rc != EOK) {
+		printf("%s: unable to register driver (%s).\n",
+		    NAME, str_error(rc));
+		return 1;
+	}
+
+	rc = devmap_device_register(DEVMAP_PATH, NULL);
+	if (rc != EOK) {
+		printf("%s: unable to register device %s (%s).\n",
+		    NAME, DEVMAP_PATH, str_error(rc));
+		return 1;
+	}
+	
+	printf("%s: accepting connections.\n", NAME);
+	hc_manager();
+	
+	return 0;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/srv/hw/bus/usb/hcd/virtual/vhcd.h
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/vhcd.h	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
+++ uspace/srv/hw/bus/usb/hcd/virtual/vhcd.h	(revision 4bc309bf9ecb5c52d870148e834fec37fd241140)
@@ -0,0 +1,56 @@
+/*
+ * 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 usb
+ * @{
+ */
+/** @file
+ * @brief Virtual USB host controller common definitions.
+ */
+#ifndef VHCD_VHCD_H_
+#define VHCD_VHCD_H_
+
+#define NAME "hcd-virt"
+#define NAMESPACE "usb"
+
+#define DEVMAP_PATH NAMESPACE "/" NAME
+
+static inline void dprintf(const char * format, ...)
+{
+	printf("%s:   ", NAME);
+	va_list args;
+	va_start(args, format);
+	vprintf(format, args);
+	va_end(args);
+	printf("\n");
+}
+
+#endif
+/**
+ * @}
+ */
