Index: .bzrignore
===================================================================
--- .bzrignore	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ .bzrignore	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -62,27 +62,7 @@
 ./uspace/app/trace/trace
 ./uspace/app/usb/usb
+./uspace/app/usbinfo/usbinfo
 ./uspace/app/virtusbkbd/vuk
-./uspace/dist/app/bdsh
-./uspace/dist/app/edit
-./uspace/dist/app/getterm
-./uspace/dist/app/klog
-./uspace/dist/app/mkfat
-./uspace/dist/app/netecho
-./uspace/dist/app/netstart
-./uspace/dist/app/nettest1
-./uspace/dist/app/nettest2
-./uspace/dist/app/ping
-./uspace/dist/app/redir
-./uspace/dist/app/sbi
-./uspace/dist/app/stats
-./uspace/dist/app/taskdump
-./uspace/dist/app/tasks
-./uspace/dist/app/tester
-./uspace/dist/app/test_serial
-./uspace/dist/app/tetris
-./uspace/dist/app/top
-./uspace/dist/app/trace
-./uspace/dist/app/usb
-./uspace/dist/app/vuk
+./uspace/dist/app/*
 ./uspace/dist/cfg/net/general
 ./uspace/dist/cfg/net/lo
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ boot/Makefile.common	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -142,7 +142,8 @@
 	$(USPACE_PATH)/app/ping/ping \
 	$(USPACE_PATH)/app/stats/stats \
-	$(USPACE_PATH)/app/virtusbkbd/vuk \
 	$(USPACE_PATH)/app/tasks/tasks \
-	$(USPACE_PATH)/app/top/top
+	$(USPACE_PATH)/app/top/top \
+	$(USPACE_PATH)/app/usbinfo/usbinfo \
+	$(USPACE_PATH)/app/virtusbkbd/vuk
 
 ifneq ($(CONFIG_BAREBONE),y)
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/Makefile	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -49,4 +49,5 @@
 	app/trace \
 	app/top \
+	app/usbinfo \
 	app/virtusbkbd \
 	app/netecho \
Index: uspace/app/usbinfo/Makefile
===================================================================
--- uspace/app/usbinfo/Makefile	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
+++ uspace/app/usbinfo/Makefile	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -0,0 +1,39 @@
+#
+# 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 = usbinfo
+
+LIBS = $(LIBUSB_PREFIX)/libusb.a $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS = -I$(LIBUSB_PREFIX)/include -I$(LIBDRV_PREFIX)/include
+
+SOURCES = \
+	dump.c \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/usbinfo/dump.c
===================================================================
--- uspace/app/usbinfo/dump.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
+++ uspace/app/usbinfo/dump.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -0,0 +1,78 @@
+/*
+ * 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 USB querying.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+
+#include "usbinfo.h"
+
+#define INDENT "  "
+
+#define BCD_INT(a) (((unsigned int)(a)) / 256)
+#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
+
+#define BCD_FMT "%x.%x"
+#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
+
+void dump_standard_device_descriptor(usb_standard_device_descriptor_t *d)
+{
+	printf("Standard device descriptor:\n");
+
+	printf(INDENT "bLength = %d\n", d->length);
+	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
+	printf(INDENT "bcdUSB = %d (" BCD_FMT ")\n", d->usb_spec_version,
+	    BCD_ARGS(d->usb_spec_version));
+	printf(INDENT "bDeviceClass = 0x%02x\n", d->device_class);
+	printf(INDENT "bDeviceSubClass = 0x%02x\n", d->device_subclass);
+	printf(INDENT "bDeviceProtocol = 0x%02x\n", d->device_protocol);
+	printf(INDENT "bMaxPacketSize0 = %d\n", d->max_packet_size);
+	printf(INDENT "idVendor = %d\n", d->vendor_id);
+	printf(INDENT "idProduct = %d\n", d->product_id);
+	printf(INDENT "bcdDevice = %d\n", d->device_version);
+	printf(INDENT "iManufacturer = %d\n", d->str_manufacturer);
+	printf(INDENT "iProduct = %d\n", d->str_product);
+	printf(INDENT "iSerialNumber = %d\n", d->str_serial_number);
+	printf(INDENT "bNumConfigurations = %d\n", d->configuration_count);
+}
+
+/** @}
+ */
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
+++ uspace/app/usbinfo/main.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -0,0 +1,129 @@
+/*
+ * 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 USB querying.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+#include <devman.h>
+#include <usb/usbdrv.h>
+#include "usbinfo.h"
+
+static void print_usage(char *app_name)
+{
+	printf(NAME ": query USB devices for descriptors\n\n");
+	printf("Usage: %s /path/to/hc usb-address\n where\n", app_name);
+	printf("   /path/to/hc   Devman path to USB host controller\n");
+	printf("   usb-address   USB address of device to be queried\n");
+	printf("\n");
+}
+
+static int connect_to_hc(const char *path)
+{
+	int rc;
+	devman_handle_t handle;
+
+	rc = devman_device_get_handle(path, &handle, 0);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	int phone = devman_device_connect(handle, 0);
+
+	return phone;
+}
+
+int main(int argc, char * argv[])
+{
+	if (argc != 3) {
+		print_usage(argv[0]);
+		return EINVAL;
+	}
+
+	char *hc_path = argv[1];
+	long int address_long = strtol(argv[2], NULL, 0);
+
+	/*
+	 * Connect to given host controller driver.
+	 */
+	int hc_phone = connect_to_hc(hc_path);
+	if (hc_phone < 0) {
+		fprintf(stderr,
+		    NAME ": unable to connect to HC at `%s': %s.\n",
+		    hc_path, str_error(hc_phone));
+		return hc_phone;
+	}
+
+	/*
+	 * Verify address is okay.
+	 */
+	usb_address_t address = (usb_address_t) address_long;
+	if ((address < 0) || (address >= USB11_ADDRESS_MAX)) {
+		fprintf(stderr, NAME ": USB address out of range.\n");
+		return ERANGE;
+	}
+
+	/*
+	 * Now, learn information about the device.
+	 */
+	int rc;
+
+	/*
+	 * Get device descriptor and dump it.
+	 */
+	usb_standard_device_descriptor_t device_descriptor;
+	usb_dprintf("usbinfo", 1,
+	    "usb_drv_req_get_device_descriptor(%d, %d, %p)\n",
+	    hc_phone, (int) address, &device_descriptor);
+
+	rc = usb_drv_req_get_device_descriptor(hc_phone, address,
+	    &device_descriptor);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to fetch standard device descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	dump_standard_device_descriptor(&device_descriptor);
+
+
+	return EOK;
+}
+
+
+/** @}
+ */
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
+++ uspace/app/usbinfo/usbinfo.h	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -0,0 +1,50 @@
+/*
+ * 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 Common header for usbinfo application.
+ */
+#ifndef USBINFO_USBINFO_H_
+#define USBINFO_USBINFO_H_
+
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+#include <usb/debug.h>
+
+
+#define NAME "usbinfo"
+
+void dump_standard_device_descriptor(usb_standard_device_descriptor_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/uhci/main.c
===================================================================
--- uspace/drv/uhci/main.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/drv/uhci/main.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -27,4 +27,5 @@
  */
 #include <usb/hcdhubd.h>
+#include <usb/debug.h>
 #include <errno.h>
 #include "uhci.h"
@@ -36,4 +37,5 @@
 static int uhci_add_device(device_t *device)
 {
+	usb_dprintf(NAME, 1, "uhci_add_device() called\n");
 	device->ops = &uhci_ops;
 
@@ -41,4 +43,5 @@
 	 * We need to announce the presence of our root hub.
 	 */
+	usb_dprintf(NAME, 2, "adding root hub\n");
 	usb_hcd_add_root_hub(device);
 
@@ -61,4 +64,5 @@
 	 */
 	sleep(5);
+	usb_dprintf_enable(NAME, 5);
 
 	return driver_main(&uhci_driver);
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/drv/vhc/connhost.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -58,5 +58,5 @@
 		case USB_DIRECTION_IN:
 			transfer->in_callback(transfer->dev,
-			    size, outcome,
+			    outcome, size,
 			    transfer->arg);
 			break;
Index: uspace/drv/vhc/debug.c
===================================================================
--- uspace/drv/vhc/debug.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/drv/vhc/debug.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -35,31 +35,8 @@
 #include <stdio.h>
 #include <ipc/ipc.h>
+#include <usb/debug.h>
 
 #include "vhcd.h"
 
-/** Current debug level. */
-int debug_level = 0;
-
-/** Debugging printf.
- * This function is intended for single-line messages as it
- * automatically prints debugging prefix at the beginning of the
- * line.
- *
- * @see printf
- * @param level Debugging level.
- */
-void dprintf(int level, const char *format, ...)
-{
-	if (level > debug_level) {
-		return;
-	}
-	
-	printf("%s(%d): ", NAME, level);
-	va_list args;
-	va_start(args, format);
-	vprintf(format, args);
-	va_end(args);
-	printf("\n");
-}
 
 /** Debug print informing of invalid call.
Index: uspace/drv/vhc/hcd.c
===================================================================
--- uspace/drv/vhc/hcd.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/drv/vhc/hcd.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -111,5 +111,5 @@
 	printf("%s: virtual USB host controller driver.\n", NAME);
 
-	debug_level = 10;
+	usb_dprintf_enable(NAME, 10);
 
 	fid_t fid = fibril_create(hc_manager_fibril, NULL);
Index: uspace/drv/vhc/vhcd.h
===================================================================
--- uspace/drv/vhc/vhcd.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/drv/vhc/vhcd.h	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -36,4 +36,6 @@
 #define VHCD_VHCD_H_
 
+#include <usb/debug.h>
+
 #define NAME "vhc"
 #define NAME_DEV "hcd-virt-dev"
@@ -43,6 +45,6 @@
 #define DEVMAP_PATH_DEV NAMESPACE "/" NAME_DEV
 
-extern int debug_level;
-void dprintf(int, const char *, ...);
+#define dprintf(level, format, ...) \
+	usb_dprintf(NAME, (level), format "\n", ##__VA_ARGS__)
 void dprintf_inval_call(int, ipc_call_t, ipcarg_t);
 
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -54,4 +54,14 @@
 	DEV_IFACE_ID(DEV_FIRST_CUSTOM_METHOD_IDX)
 
+/*
+ * The first argument is actually method (as the "real" method is used
+ * for indexing into interfaces.
+ */
+
+#define DEV_IPC_GET_ARG1(call) IPC_GET_ARG2((call))
+#define DEV_IPC_GET_ARG2(call) IPC_GET_ARG3((call))
+#define DEV_IPC_GET_ARG3(call) IPC_GET_ARG4((call))
+#define DEV_IPC_GET_ARG4(call) IPC_GET_ARG5((call))
+
 
 #endif
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -108,5 +108,5 @@
 	}
 
-	devman_handle_t handle = IPC_GET_ARG1(*call);
+	devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
 
 	usb_address_t address;
@@ -122,5 +122,5 @@
     ipc_callid_t callid, ipc_call_t *call)
 {
-	ipcarg_t buffer_hash = IPC_GET_ARG1(*call);
+	ipcarg_t buffer_hash = DEV_IPC_GET_ARG1(*call);
 	async_transaction_t * trans = (async_transaction_t *)buffer_hash;
 	if (trans == NULL) {
@@ -144,5 +144,5 @@
 		accepted_size = trans->size;
 	}
-	async_data_read_finalize(callid, trans->buffer, accepted_size);
+	async_data_read_finalize(cid, trans->buffer, accepted_size);
 
 	ipc_answer_1(callid, EOK, accepted_size);
@@ -211,6 +211,6 @@
 	}
 
-	usb_address_t address = (usb_address_t) IPC_GET_ARG1(*call);
-	devman_handle_t handle = (devman_handle_t) IPC_GET_ARG2(*call);
+	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
+	devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
 
 	int rc = usb_iface->bind_address(device, address, handle);
@@ -229,5 +229,5 @@
 	}
 
-	usb_address_t address = (usb_address_t) IPC_GET_ARG1(*call);
+	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
 
 	int rc = usb_iface->release_address(device, address);
@@ -275,8 +275,8 @@
 	}
 
-	size_t expected_len = IPC_GET_ARG3(*call);
+	size_t expected_len = DEV_IPC_GET_ARG3(*call);
 	usb_target_t target = {
-		.address = IPC_GET_ARG1(*call),
-		.endpoint = IPC_GET_ARG2(*call)
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
 	};
 
@@ -327,8 +327,8 @@
 	}
 
-	size_t len = IPC_GET_ARG3(*call);
+	size_t len = DEV_IPC_GET_ARG3(*call);
 	usb_target_t target = {
-		.address = IPC_GET_ARG1(*call),
-		.endpoint = IPC_GET_ARG2(*call)
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
 	};
 
@@ -384,6 +384,6 @@
 
 	usb_target_t target = {
-		.address = IPC_GET_ARG1(*call),
-		.endpoint = IPC_GET_ARG2(*call)
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
 	};
 
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/usb/Makefile	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -34,4 +34,6 @@
 SOURCES = \
 	src/addrkeep.c \
+	src/debug.c \
+	src/drvpsync.c \
 	src/hcdhubd.c \
 	src/hcdrv.c \
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
+++ uspace/lib/usb/include/usb/debug.h	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -0,0 +1,42 @@
+/*
+ * 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 Debugging related functions.
+ */
+#ifndef LIBUSB_DEBUG_H_
+#define LIBUSB_DEBUG_H_
+
+void usb_dprintf(const char *tag, int level, const char *format, ...);
+void usb_dprintf_enable(const char *tag, int level);
+
+
+#endif
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/usb/include/usb/usb.h	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -71,4 +71,6 @@
 /** Default USB address. */
 #define USB_ADDRESS_DEFAULT 0
+/** Maximum address number in USB 1.1. */
+#define USB11_ADDRESS_MAX 128
 
 /** USB endpoint number type.
Index: uspace/lib/usb/include/usb/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/usb/include/usb/usbdrv.h	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -38,4 +38,6 @@
 #include <usb/usb.h>
 #include <driver.h>
+#include <usb/devreq.h>
+#include <usb/descriptor.h>
 
 int usb_drv_hc_connect(device_t *, unsigned int);
@@ -54,4 +56,9 @@
     void *, size_t, size_t *, usb_handle_t *);
 
+int usb_drv_psync_interrupt_out(int, usb_target_t, void *, size_t);
+int usb_drv_psync_interrupt_in(int, usb_target_t, void *, size_t, size_t *);
+
+
+
 int usb_drv_async_control_write_setup(int, usb_target_t,
     void *, size_t, usb_handle_t *);
@@ -60,4 +67,9 @@
 int usb_drv_async_control_write_status(int, usb_target_t,
     usb_handle_t *);
+
+int usb_drv_psync_control_write_setup(int, usb_target_t, void *, size_t);
+int usb_drv_psync_control_write_data(int, usb_target_t, void *, size_t);
+int usb_drv_psync_control_write_status(int, usb_target_t);
+
 
 int usb_drv_async_control_read_setup(int, usb_target_t,
@@ -68,8 +80,15 @@
     usb_handle_t *);
 
+int usb_drv_psync_control_read_setup(int, usb_target_t, void *, size_t);
+int usb_drv_psync_control_read_data(int, usb_target_t, void *, size_t, size_t *);
+int usb_drv_psync_control_read_status(int, usb_target_t);
+
+
 int usb_drv_async_wait_for(usb_handle_t);
 
 
 int usb_drv_req_set_address(int, usb_address_t, usb_address_t);
+int usb_drv_req_get_device_descriptor(int, usb_address_t,
+    usb_standard_device_descriptor_t *);
 
 #endif
Index: uspace/lib/usb/src/debug.c
===================================================================
--- uspace/lib/usb/src/debug.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
+++ uspace/lib/usb/src/debug.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -0,0 +1,160 @@
+/*
+ * 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 Debugging support.
+ */
+#include <adt/list.h>
+#include <fibril_synch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <usb/debug.h>
+
+/** Debugging tag. */
+typedef struct {
+	/** Linked list member. */
+	link_t link;
+	/** Tag name.
+	 * We always have a private copy of the name.
+	 */
+	char *tag;
+	/** Enabled level of debugging. */
+	int level;
+} usb_debug_tag_t;
+
+/** Get instance of usb_debug_tag_t from link_t. */
+#define USB_DEBUG_TAG_INSTANCE(iterator) \
+	list_get_instance(iterator, usb_debug_tag_t, link)
+
+/** List of all known tags. */
+static LIST_INITIALIZE(tag_list);
+/** Mutex guard for the list of all tags. */
+static FIBRIL_MUTEX_INITIALIZE(tag_list_guard);
+
+/** Find or create new tag with given name.
+ *
+ * @param tagname Tag name.
+ * @return Debug tag structure.
+ * @retval NULL Out of memory.
+ */
+static usb_debug_tag_t *get_tag(const char *tagname)
+{
+	link_t *link;
+	for (link = tag_list.next; \
+	    link != &tag_list; \
+	    link = link->next) {
+		usb_debug_tag_t *tag = USB_DEBUG_TAG_INSTANCE(link);
+		if (str_cmp(tag->tag, tagname) == 0) {
+			return tag;
+		}
+	}
+
+	/*
+	 * Tag not found, we will create a new one.
+	 */
+	usb_debug_tag_t *new_tag = malloc(sizeof(usb_debug_tag_t));
+	int rc = asprintf(&new_tag->tag, "%s", tagname);
+	if (rc < 0) {
+		free(new_tag);
+		return NULL;
+	}
+	list_initialize(&new_tag->link);
+	new_tag->level = 1;
+
+	/*
+	 * Append it to the end of known tags.
+	 */
+	list_append(&new_tag->link, &tag_list);
+
+	return new_tag;
+}
+
+/** Print debugging information.
+ * If the tag is used for the first time, its structures are automatically
+ * created and initial verbosity level is set to 1.
+ *
+ * @param tagname Tag name.
+ * @param level Level (verbosity) of the message.
+ * @param format Formatting string for printf().
+ */
+void usb_dprintf(const char *tagname, int level, const char *format, ...)
+{
+	fibril_mutex_lock(&tag_list_guard);
+	usb_debug_tag_t *tag = get_tag(tagname);
+	if (tag == NULL) {
+		printf("USB debug: FATAL ERROR - failed to create tag.\n");
+		goto leave;
+	}
+
+	if (tag->level < level) {
+		goto leave;
+	}
+
+	va_list args;
+	va_start(args, format);
+
+	printf("[%s:%d]: ", tagname, level);
+	vprintf(format, args);
+
+	va_end(args);
+
+leave:
+	fibril_mutex_unlock(&tag_list_guard);
+}
+
+/** Enable debugging prints for given tag.
+ *
+ * Setting level to <i>n</i> will cause that only printing messages
+ * with level lower or equal to <i>n</i> will be printed.
+ *
+ * @param tagname Tag name.
+ * @param level Enabled level.
+ */
+void usb_dprintf_enable(const char *tagname, int level)
+{
+	fibril_mutex_lock(&tag_list_guard);
+	usb_debug_tag_t *tag = get_tag(tagname);
+	if (tag == NULL) {
+		printf("USB debug: FATAL ERROR - failed to create tag.\n");
+		goto leave;
+	}
+
+	tag->level = level;
+
+leave:
+	fibril_mutex_unlock(&tag_list_guard);
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/drvpsync.c
===================================================================
--- uspace/lib/usb/src/drvpsync.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
+++ uspace/lib/usb/src/drvpsync.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -0,0 +1,141 @@
+/*
+ * 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 Implementation of pseudo-synchronous transfers.
+ */
+#include <usb/usbdrv.h>
+#include <usbhc_iface.h>
+#include <errno.h>
+
+int usb_drv_psync_interrupt_out(int phone, usb_target_t target,
+    void *buffer, size_t size)
+{
+	usb_handle_t h;
+	int rc;
+	rc = usb_drv_async_interrupt_out(phone, target, buffer, size, &h);
+	if (rc != EOK) {
+		return rc;
+	}
+	return usb_drv_async_wait_for(h);
+}
+
+int usb_drv_psync_interrupt_in(int phone, usb_target_t target,
+    void *buffer, size_t size, size_t *actual_size)
+{
+	usb_handle_t h;
+	int rc;
+	rc = usb_drv_async_interrupt_in(phone, target, buffer, size,
+	    actual_size, &h);
+	if (rc != EOK) {
+		return rc;
+	}
+	return usb_drv_async_wait_for(h);
+}
+
+
+
+int usb_drv_psync_control_write_setup(int phone, usb_target_t target,
+    void *buffer, size_t size)
+{
+	usb_handle_t h;
+	int rc;
+	rc = usb_drv_async_control_write_setup(phone, target, buffer, size, &h);
+	if (rc != EOK) {
+		return rc;
+	}
+	return usb_drv_async_wait_for(h);
+}
+
+int usb_drv_psync_control_write_data(int phone, usb_target_t target,
+    void *buffer, size_t size)
+{
+	usb_handle_t h;
+	int rc;
+	rc = usb_drv_async_control_write_data(phone, target, buffer, size, &h);
+	if (rc != EOK) {
+		return rc;
+	}
+	return usb_drv_async_wait_for(h);
+}
+
+int usb_drv_psync_control_write_status(int phone, usb_target_t target)
+{
+	usb_handle_t h;
+	int rc;
+	rc = usb_drv_async_control_write_status(phone, target, &h);
+	if (rc != EOK) {
+		return rc;
+	}
+	return usb_drv_async_wait_for(h);
+}
+
+
+
+int usb_drv_psync_control_read_setup(int phone, usb_target_t target,
+    void *buffer, size_t size)
+{
+	usb_handle_t h;
+	int rc;
+	rc = usb_drv_async_control_read_setup(phone, target, buffer, size, &h);
+	if (rc != EOK) {
+		return rc;
+	}
+	return usb_drv_async_wait_for(h);
+}
+
+int usb_drv_psync_control_read_data(int phone, usb_target_t target,
+    void *buffer, size_t size, size_t *actual_size)
+{
+	usb_handle_t h;
+	int rc;
+	rc = usb_drv_async_control_read_data(phone, target, buffer, size,
+	    actual_size, &h);
+	if (rc != EOK) {
+		return rc;
+	}
+	return usb_drv_async_wait_for(h);
+}
+
+int usb_drv_psync_control_read_status(int phone, usb_target_t target)
+{
+	usb_handle_t h;
+	int rc;
+	rc = usb_drv_async_control_read_status(phone, target, &h);
+	if (rc != EOK) {
+		return rc;
+	}
+	return usb_drv_async_wait_for(h);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/usbdrvreq.c
===================================================================
--- uspace/lib/usb/src/usbdrvreq.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/usb/src/usbdrvreq.c	(revision 818dc001e1775bf0bf356f9911600e641fa43e5a)
@@ -34,5 +34,4 @@
  */
 #include <usb/usbdrv.h>
-#include <usb/devreq.h>
 #include <errno.h>
 
@@ -95,4 +94,88 @@
 }
 
+/** Retrieve device descriptor of connected USB device.
+ *
+ * @param[in] phone Open phone to HC driver.
+ * @param[in] address Device USB address.
+ * @param[out] descriptor Storage for the device descriptor.
+ * @return Error code.
+ * @retval EBADMEM @p descriptor is NULL.
+ */
+int usb_drv_req_get_device_descriptor(int phone, usb_address_t address,
+    usb_standard_device_descriptor_t *descriptor)
+{
+	if (descriptor == NULL) {
+		return EBADMEM;
+	}
+
+	/* Prepare the target. */
+	usb_target_t target = {
+		.address = address,
+		.endpoint = 0
+	};
+
+	/* Prepare the setup packet. */
+	usb_device_request_setup_packet_t setup_packet = {
+		.request_type = 128,
+		.request = USB_DEVREQ_GET_DESCRIPTOR,
+		.index = 0,
+		.length = sizeof(usb_standard_device_descriptor_t)
+	};
+	setup_packet.value_high = USB_DESCTYPE_DEVICE;
+	setup_packet.value_low = 0;
+
+	usb_handle_t handle;
+	int rc;
+
+	/* Start the control read transfer. */
+	rc = usb_drv_async_control_read_setup(phone, target,
+	    &setup_packet, sizeof(usb_device_request_setup_packet_t), &handle);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = usb_drv_async_wait_for(handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Retrieve the descriptor. */
+	size_t actually_transferred = 0;
+	usb_standard_device_descriptor_t descriptor_tmp;
+	rc = usb_drv_async_control_read_data(phone, target,
+	    &descriptor_tmp, sizeof(usb_standard_device_descriptor_t),
+	    &actually_transferred, &handle);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = usb_drv_async_wait_for(handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Finish the control read transfer. */
+	rc = usb_drv_async_control_read_status(phone, target, &handle);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = usb_drv_async_wait_for(handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (actually_transferred < sizeof(usb_standard_device_descriptor_t)) {
+		return ELIMIT;
+	}
+
+	/*
+	 * Everything is okay, copy the descriptor.
+	 */
+	memcpy(descriptor, &descriptor_tmp,
+	    sizeof(usb_standard_device_descriptor_t));
+
+	return EOK;
+}
+
+
+
 /**
  * @}
