Index: .bzrignore
===================================================================
--- .bzrignore	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ .bzrignore	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -84,4 +84,5 @@
 ./uspace/drv/test1/test1
 ./uspace/drv/test2/test2
+./uspace/drv/ehci-hcd/ehci-hcd
 ./uspace/drv/uhci-hcd/uhci-hcd
 ./uspace/drv/uhci-rhd/uhci-rhd
@@ -89,4 +90,5 @@
 ./uspace/drv/usbhid/usbhid
 ./uspace/drv/usbmid/usbmid
+./uspace/drv/usbmouse/usbmouse
 ./uspace/drv/vhc/vhc
 ./uspace/srv/bd/ata_bd/ata_bd
Index: Makefile
===================================================================
--- Makefile	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -42,5 +42,5 @@
 CONFIG_HEADER = config.h
 
-.PHONY: all precheck cscope autotool config_auto config_default config distclean clean check
+.PHONY: all precheck cscope autotool config_auto config_default config distclean clean check distfile dist
 
 all: $(COMMON_MAKEFILE) $(COMMON_HEADER) $(CONFIG_MAKEFILE) $(CONFIG_HEADER)
@@ -64,4 +64,6 @@
 endif
 
+# Autotool (detects compiler features)
+
 $(COMMON_MAKEFILE): autotool
 $(COMMON_HEADER): autotool
@@ -70,4 +72,6 @@
 	$(AUTOTOOL)
 	-[ -f $(COMMON_HEADER_PREV) ] && diff -q $(COMMON_HEADER_PREV) $(COMMON_HEADER) && mv -f $(COMMON_HEADER_PREV) $(COMMON_HEADER)
+
+# Build-time configuration
 
 $(CONFIG_MAKEFILE): config_default
@@ -84,6 +88,16 @@
 	$(CONFIG) $<
 
+# Distribution files
+
+distfile: all
+	$(MAKE) -C dist distfile
+
+dist:
+	$(MAKE) -C dist dist
+
+# Cleaning
+
 distclean: clean
-	rm -f $(CSCOPE).out $(COMMON_MAKEFILE) $(COMMON_HEADER) $(COMMON_HEADER_PREV) $(CONFIG_MAKEFILE) $(CONFIG_HEADER) tools/*.pyc tools/checkers/*.pyc
+	rm -f $(CSCOPE).out $(COMMON_MAKEFILE) $(COMMON_HEADER) $(COMMON_HEADER_PREV) $(CONFIG_MAKEFILE) $(CONFIG_HEADER) tools/*.pyc tools/checkers/*.pyc dist/HelenOS-*
 
 clean:
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ boot/arch/amd64/Makefile.inc	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -43,4 +43,5 @@
 	isa \
 	ns8250 \
+	ehci-hcd \
 	uhci-hcd \
 	uhci-rhd \
@@ -48,4 +49,5 @@
 	usbhid \
 	usbmid \
+	usbmouse \
 	vhc
 
Index: boot/arch/mips32/src/asm.S
===================================================================
--- boot/arch/mips32/src/asm.S	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ boot/arch/mips32/src/asm.S	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -41,7 +41,20 @@
 
 start:
-	/* Setup CPU map (on msim this code
-	   is executed in parallel on all CPUs,
-	   but it not an issue) */
+	/*
+	 * Setup the CP0 configuration
+	 *  - Disable 64-bit kernel addressing mode
+	 *  - DIsable 64-bit supervisor adressing mode
+	 *  - Disable 64-bit user addressing mode
+	 */
+	mfc0 $a0, $status
+	la $a1, 0xffffff1f
+	and $a0, $a1, $a0
+	mtc0 $a0, $status
+	
+	/*
+	 * Setup CPU map (on msim this code
+	 * is executed in parallel on all CPUs,
+	 * but it not an issue).
+	 */
 	la $a0, PA2KA(CPUMAP_OFFSET)
 	
@@ -94,6 +107,8 @@
 	lw $k1, ($k0)
 	
-	/* If we are not running on BSP
-	   then end in an infinite loop  */
+	/*
+	 * If we are not running on BSP
+	 * then end in an infinite loop.
+	 */
 	beq $k1, $zero, bsp
 	nop
@@ -127,9 +142,10 @@
 
 jump_to_kernel:
-	#
-	# TODO:
-	# Make sure that the I-cache, D-cache and memory are mutually coherent
-	# before passing control to the copied code.
-	#
+	/*
+	 * TODO:
+	 *
+	 * Make sure that the I-cache, D-cache and memory are mutually
+	 * coherent before passing control to the copied code.
+	 */
 	j $a0
 	nop
Index: boot/arch/sparc64/include/arch.h
===================================================================
--- boot/arch/sparc64/include/arch.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ boot/arch/sparc64/include/arch.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -41,4 +41,5 @@
 #define STACK_BIAS                   2047
 #define STACK_WINDOW_SAVE_AREA_SIZE  (16 * 8)
+#define STACK_ARG_SAVE_AREA_SIZE     (6 * 8)
 
 #define NWINDOWS  8
Index: boot/arch/sparc64/src/asm.S
===================================================================
--- boot/arch/sparc64/src/asm.S	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ boot/arch/sparc64/src/asm.S	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -152,5 +152,5 @@
 .global ofw
 ofw:
-	save %sp, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
+	save %sp, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
 	set ofw_cif, %l0
 	ldx [%l0], %l0
Index: boot/arch/sparc64/src/main.c
===================================================================
--- boot/arch/sparc64/src/main.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ boot/arch/sparc64/src/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -190,4 +190,5 @@
 	bootinfo.memmap.zones[0].start += OBP_BIAS;
 	bootinfo.memmap.zones[0].size -= OBP_BIAS;
+	bootinfo.memmap.total -= OBP_BIAS;
 }
 
@@ -204,4 +205,7 @@
 	bootinfo.physmem_start = ofw_get_physmem_start();
 	ofw_memmap(&bootinfo.memmap);
+
+	if (arch == ARCH_SUN4V)
+		sun4v_fixups();
 	
 	void *bootinfo_pa = ofw_translate(&bootinfo);
@@ -253,21 +257,16 @@
 		
 		/*
-		 * At this point, we claim the physical memory that we are
-		 * going to use. We should be safe in case of the virtual
+		 * At this point, we claim and map the physical memory that we
+		 * are going to use. We should be safe in case of the virtual
 		 * address space because the OpenFirmware, according to its
-		 * SPARC binding, should restrict its use of virtual memory
-		 * to addresses from [0xffd00000; 0xffefffff] and
-		 * [0xfe000000; 0xfeffffff].
-		 *
-		 * We don't map this piece of memory. We simply rely on
-		 * SILO to have it done for us already in this case.
-		 *
-		 * XXX SILO only maps 8 MB for us here. We should improve
-		 *     this code to be totally independent on the behavior
-		 *     of SILO.
-		 *
+		 * SPARC binding, should restrict its use of virtual memory to
+		 * addresses from [0xffd00000; 0xffefffff] and [0xfe000000;
+		 * 0xfeffffff].
 		 */
 		ofw_claim_phys(bootinfo.physmem_start + dest[i - 1],
 		    ALIGN_UP(components[i - 1].inflated, PAGE_SIZE));
+		
+		ofw_map(bootinfo.physmem_start + dest[i - 1], dest[i - 1],
+		    ALIGN_UP(components[i - 1].inflated, PAGE_SIZE), -1);
 		
 		int err = inflate(components[i - 1].start, components[i - 1].size,
@@ -304,7 +303,4 @@
 		sun4u_smp();
 	
-	if (arch == ARCH_SUN4V)
-		sun4v_fixups();
-	
 	printf("Booting the kernel ...\n");
 	jump_to_kernel(bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo, subarch,
Index: boot/generic/src/balloc.c
===================================================================
--- boot/generic/src/balloc.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ boot/generic/src/balloc.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -65,4 +65,4 @@
 void *balloc_rebase(void *ptr)
 {
-	return (void *) ((uintptr_t) ptr - phys_base + ballocs->base);
+	return (void *) (((uintptr_t) ptr - phys_base) + ballocs->base);
 }
Index: dist/Makefile
===================================================================
--- dist/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ dist/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2011 Jiri Svoboda
+# 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.
+#
+
+-include ../version
+-include ../Makefile.config
+-include ../boot/arch/$(BARCH)/Makefile.inc
+-include ../boot/Makefile.common
+
+PROFILES = amd64 arm32/GXemul arm32/integratorcp arm32/gta02 ia32 \
+    ia64/i460GX ia64/ski mips32/GXemul mips32/msim sparc64/niagara \
+    sparc64/serengeti sparc64/ultra
+
+ifdef POST_OUTPUT
+	IMGFILE = $(POST_OUTPUT)
+else
+	IMGFILE = $(BOOT_OUTPUT)
+endif
+
+SUFFIX = $(suffix $(IMGFILE))
+DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX)
+
+.PHONY: all clean dist distfile
+
+all: distfile
+distfile: $(DISTFILE)
+
+$(DISTFILE): $(IMGFILE)
+	cp $< $@
+
+dist:
+	for profile in $(PROFILES); do \
+		$(MAKE) -C .. clean ; \
+		$(MAKE) -C .. PROFILE=$$profile distfile ; \
+	done
+
+clean:
+	rm -f $(DISTFILE)
Index: kernel/arch/sparc64/src/sun4v/asm.S
===================================================================
--- kernel/arch/sparc64/src/sun4v/asm.S	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ kernel/arch/sparc64/src/sun4v/asm.S	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -41,6 +41,5 @@
 .global switch_to_userspace
 switch_to_userspace:
-	wrpr PSTATE_PRIV_BIT, %pstate
-	save %o1, -STACK_WINDOW_SAVE_AREA_SIZE, %sp
+	save %o1, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
 	flushw
 	wrpr %g0, 0, %cleanwin		! avoid information leak
Index: tools/toolchain.sh
===================================================================
--- tools/toolchain.sh	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ tools/toolchain.sh	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -28,4 +28,74 @@
 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
+
+GMP_MAIN=<<EOF
+#define GCC_GMP_VERSION_NUM(a, b, c) \
+	(((a) << 16L) | ((b) << 8) | (c))
+
+#define GCC_GMP_VERSION \
+	GCC_GMP_VERSION_NUM(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, __GNU_MP_VERSION_PATCHLEVEL)
+
+#if GCC_GMP_VERSION < GCC_GMP_VERSION_NUM(4,3,2)
+	choke me
+#endif
+EOF
+
+MPFR_MAIN=<<EOF
+#if MPFR_VERSION < MPFR_VERSION_NUM(2, 4, 2)
+choke me
+	#endif
+EOF
+
+MPC_MAIN=<<EOF
+#if MPC_VERSION < MPC_VERSION_NUM(0, 8, 1)
+	choke me
+#endif
+EOF
+
+#
+# Check if the library described in the argument
+# exists and has acceptable version.
+#
+check_dependency() {
+	DEPENDENCY="$1"
+	HEADER="$2"
+	BODY="$3"
+	
+	FNAME="/tmp/conftest-$$"
+	
+	echo "#include ${HEADER}" > "${FNAME}.c"
+	echo >> "${FNAME}.c"
+	echo "int main()" >> "${FNAME}.c"
+	echo "{" >> "${FNAME}.c"
+	echo "${BODY}" >> "${FNAME}.c"
+	echo "	return 0;" >> "${FNAME}.c"
+	echo "}" >> "${FNAME}.c"
+	
+	cc -c -o "${FNAME}.o" "${FNAME}.c" 2> "${FNAME}.log"
+	RC="$?"
+	
+	if [ "$RC" -ne "0" ] ; then
+		echo " ${DEPENDENCY} not found, too old or compiler error."
+		echo " Please recheck manually the source file \"${FNAME}.c\"."
+		echo " The compilation of the toolchain is probably going to fail,"
+		echo " you have been warned."
+		echo
+		echo " ===== Compiler output ====="
+		cat "${FNAME}.log"
+		echo " ==========================="
+		echo
+	else
+		echo " ${DEPENDENCY} found"
+		rm -f "${FNAME}.log" "${FNAME}.o" "${FNAME}.c"
+	fi
+}
+
+check_dependecies() {
+	echo ">>> Basic dependency check"
+	check_dependency "GMP" "<gmp.h>" "${GMP_MAIN}"
+	check_dependency "MPFR" "<mpfr.h>" "${MPFR_MAIN}"
+	check_dependency "MPC" "<mpc.h>" "${MPC_MAIN}"
+	echo
+}
 
 check_error() {
@@ -69,4 +139,8 @@
 	echo " sparc64    SPARC V9"
 	echo " all        build all targets"
+	echo
+	echo "The toolchain will be installed to the directory specified by"
+	echo "the CROSS_PREFIX environment variable. If the variable is not"
+	echo "defined, /usr/local will be used by default."
 	echo
 	
@@ -118,6 +192,4 @@
 	echo " - native C library with headers"
 	echo
-	
-	show_countdown 10
 }
 
@@ -281,4 +353,6 @@
 
 show_dependencies
+check_dependecies
+show_countdown 10
 
 case "$1" in
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -117,4 +117,5 @@
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259 \
+		drv/ehci-hcd \
 		drv/uhci-hcd \
 		drv/uhci-rhd \
@@ -122,4 +123,5 @@
 		drv/usbhub \
 		drv/usbmid \
+		drv/usbmouse \
 		drv/vhc
 endif
@@ -133,4 +135,5 @@
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259 \
+		drv/ehci-hcd \
 		drv/uhci-hcd \
 		drv/uhci-rhd \
@@ -138,4 +141,5 @@
 		drv/usbhub \
 		drv/usbmid \
+		drv/usbmouse \
 		drv/vhc
 endif
Index: uspace/app/bdsh/cmds/modules/mkfile/mkfile.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mkfile/mkfile.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/app/bdsh/cmds/modules/mkfile/mkfile.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -125,5 +125,5 @@
 
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "s:h", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
Index: uspace/app/bdsh/cmds/modules/mount/mount.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mount/mount.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/app/bdsh/cmds/modules/mount/mount.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,4 +31,5 @@
 #include <vfs/vfs.h>
 #include <errno.h>
+#include <getopt.h>
 #include "config.h"
 #include "util.h"
@@ -40,5 +41,11 @@
 static const char *cmdname = "mount";
 
-/* Dispays help for mount in various levels */
+static struct option const long_options[] = {
+	{ "help", no_argument, 0, 'h' },
+	{ 0, 0, 0, 0 }
+};
+
+
+/* Displays help for mount in various levels */
 void help_cmd_mount(unsigned int level)
 {
@@ -59,10 +66,19 @@
 	unsigned int argc;
 	const char *mopts = "";
-	int rc;
+	int rc, c, opt_ind;
 
 	argc = cli_count_args(argv);
 
+	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
+		c = getopt_long(argc, argv, "h", long_options, &opt_ind);
+		switch (c) {
+		case 'h':
+			help_cmd_mount(HELP_LONG);
+			return CMD_SUCCESS;
+		}
+	}
+
 	if ((argc < 4) || (argc > 5)) {
-		printf("%s: invalid number of arguments.\n",
+		printf("%s: invalid number of arguments. Try `mount --help'\n",
 		    cmdname);
 		return CMD_FAILURE;
Index: uspace/doc/doxygroups.h
===================================================================
--- uspace/doc/doxygroups.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/doc/doxygroups.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -245,4 +245,10 @@
 
 	/**
+	 * @defgroup drvusbmouse USB mouse driver
+	 * @ingroup usb
+	 * @brief USB driver for mouse with boot protocol.
+	 */
+
+	/**
 	 * @defgroup drvusbuhci UHCI driver
 	 * @ingroup usb
@@ -250,2 +256,9 @@
 	 */
 
+	/**
+	 * @defgroup drvusbehci EHCI driver
+	 * @ingroup usb
+	 * @brief Driver for EHCI host controller.
+	 */
+
+
Index: uspace/drv/ehci-hcd/Makefile
===================================================================
--- uspace/drv/ehci-hcd/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/ehci-hcd/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2011 Jan Vesely
+# 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 = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+BINARY = ehci-hcd
+
+SOURCES = \
+	main.c \
+	pci.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/ehci-hcd/ehci-hcd.ma
===================================================================
--- uspace/drv/ehci-hcd/ehci-hcd.ma	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/ehci-hcd/ehci-hcd.ma	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,38 @@
+10 pci/ven=1002&dev=4345
+10 pci/ven=1002&dev=4386
+10 pci/ven=1002&dev=4396
+10 pci/ven=1022&dev=7463
+10 pci/ven=1022&dev=7808
+10 pci/ven=102f&dev=01b5
+10 pci/ven=10cf&dev=1415
+10 pci/ven=10de&dev=00e8
+10 pci/ven=10de&dev=055f
+10 pci/ven=10de&dev=056a
+10 pci/ven=10de&dev=077c
+10 pci/ven=10de&dev=077e
+10 pci/ven=10de&dev=0aa6
+10 pci/ven=10de&dev=0aa9
+10 pci/ven=10de&dev=0aaa
+10 pci/ven=10de&dev=0d9d
+10 pci/ven=1166&dev=0414
+10 pci/ven=1166&dev=0416
+10 pci/ven=1414&dev=5805
+10 pci/ven=1414&dev=5807
+10 pci/ven=15ad&dev=0770
+10 pci/ven=17a0&dev=8084
+10 pci/ven=8086&dev=24cd
+10 pci/ven=8086&dev=24dd
+10 pci/ven=8086&dev=265c
+10 pci/ven=8086&dev=268c
+10 pci/ven=8086&dev=27cc
+10 pci/ven=8086&dev=2836
+10 pci/ven=8086&dev=283a
+10 pci/ven=8086&dev=293a
+10 pci/ven=8086&dev=293c
+10 pci/ven=8086&dev=3a3a
+10 pci/ven=8086&dev=3a3c
+10 pci/ven=8086&dev=3a6a
+10 pci/ven=8086&dev=3a6c
+10 pci/ven=8086&dev=8117
+10 pci/ven=8086&dev=8807
+10 pci/ven=8086&dev=880f
Index: uspace/drv/ehci-hcd/main.c
===================================================================
--- uspace/drv/ehci-hcd/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/ehci-hcd/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 usbdrvehci
+ * @{
+ */
+/** @file
+ * Main routines of EHCI driver.
+ */
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
+#include <device/hw_res.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "pci.h"
+
+#define NAME "ehci-hcd"
+
+static int ehci_add_device(ddf_dev_t *device);
+/*----------------------------------------------------------------------------*/
+static driver_ops_t ehci_driver_ops = {
+	.add_device = ehci_add_device,
+};
+/*----------------------------------------------------------------------------*/
+static driver_t ehci_driver = {
+	.name = NAME,
+	.driver_ops = &ehci_driver_ops
+};
+/*----------------------------------------------------------------------------*/
+/** Initializes a new ddf driver instance of EHCI hcd.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int ehci_add_device(ddf_dev_t *device)
+{
+	assert(device);
+#define CHECK_RET_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	return ret; \
+}
+
+	usb_log_info("uhci_add_device() called\n");
+
+	uintptr_t mem_reg_base = 0;
+	size_t mem_reg_size = 0;
+	int irq = 0;
+
+	int ret =
+	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
+	CHECK_RET_RETURN(ret,
+	    "Failed(%d) to get memory addresses:.\n", ret, device->handle);
+	usb_log_info("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n",
+	    mem_reg_base, mem_reg_size, irq);
+
+	ret = pci_disable_legacy(device);
+	CHECK_RET_RETURN(ret,
+	    "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret));
+
+	return EOK;
+#undef CHECK_RET_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initializes global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_ERROR, NAME);
+	return ddf_driver_main(&ehci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/ehci-hcd/pci.c
===================================================================
--- uspace/drv/ehci-hcd/pci.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/ehci-hcd/pci.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 drvusbehci
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the EHCI driver.
+ */
+#include <errno.h>
+#include <assert.h>
+#include <as.h>
+#include <devman.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <device/hw_res.h>
+
+#include <usb/debug.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+#define PAGE_SIZE_MASK 0xfffff000
+
+#define HCC_PARAMS_OFFSET 0x8
+#define HCC_PARAMS_EECP_MASK 0xff
+#define HCC_PARAMS_EECP_OFFSET 8
+
+#define CMD_OFFSET 0x0
+#define CONFIGFLAG_OFFSET 0x40
+
+#define USBCMD_RUN 1
+
+#define USBLEGSUP_OFFSET 0
+#define USBLEGSUP_BIOS_CONTROL (1 << 16)
+#define USBLEGSUP_OS_CONTROL (1 << 24)
+#define USBLEGCTLSTS_OFFSET 4
+
+#define DEFAULT_WAIT 10000
+#define WAIT_STEP 10
+
+/** Get address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] mem_reg_address Base address of the memory range.
+ * @param[out] mem_reg_size Size of the memory range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(ddf_dev_t *dev,
+    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
+{
+	assert(dev != NULL);
+
+	int parent_phone = devman_parent_device_connect(dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	int rc;
+
+	hw_resource_list_t hw_resources;
+	rc = hw_res_get_resource_list(parent_phone, &hw_resources);
+	if (rc != EOK) {
+		async_hangup(parent_phone);
+		return rc;
+	}
+
+	uintptr_t mem_address = 0;
+	size_t mem_size = 0;
+	bool mem_found = false;
+
+	int irq = 0;
+	bool irq_found = false;
+
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type)
+		{
+		case INTERRUPT:
+			irq = res->res.interrupt.irq;
+			irq_found = true;
+			usb_log_debug2("Found interrupt: %d.\n", irq);
+			break;
+
+		case MEM_RANGE:
+			if (res->res.mem_range.address != 0
+			    && res->res.mem_range.size != 0 ) {
+				mem_address = res->res.mem_range.address;
+				mem_size = res->res.mem_range.size;
+				usb_log_debug2("Found mem: %llx %zu.\n",
+				    mem_address, mem_size);
+				mem_found = true;
+				}
+		default:
+			break;
+		}
+	}
+
+	if (mem_found && irq_found) {
+		*mem_reg_address = mem_address;
+		*mem_reg_size = mem_size;
+		*irq_no = irq;
+		rc = EOK;
+	} else {
+		rc = ENOENT;
+	}
+
+	async_hangup(parent_phone);
+	return rc;
+}
+/*----------------------------------------------------------------------------*/
+/** Calls the PCI driver with a request to enable interrupts
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_enable_interrupts(ddf_dev_t *device)
+{
+	int parent_phone =
+	    devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+	bool enabled = hw_res_enable_interrupt(parent_phone);
+	async_hangup(parent_phone);
+	return enabled ? EOK : EIO;
+}
+/*----------------------------------------------------------------------------*/
+/** Implements BIOS handoff routine as decribed in EHCI spec
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_disable_legacy(ddf_dev_t *device)
+{
+	assert(device);
+	int parent_phone = devman_parent_device_connect(device->handle,
+		IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+#define CHECK_RET_HANGUP_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		async_hangup(parent_phone); \
+		return ret; \
+	} else (void)0
+
+
+	/* read register space BASE BAR */
+	sysarg_t address = 0x10;
+	sysarg_t value;
+
+	int ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+	    IPC_M_CONFIG_SPACE_READ_32, address, &value);
+	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read PCI config space.\n",
+	    ret);
+	usb_log_info("Register space BAR at %p:%x.\n", address, value);
+
+	/* clear lower byte, it's not part of the BASE address */
+	uintptr_t registers = (value & 0xffffff00);
+	usb_log_info("Memory registers BASE address:%p.\n", registers);
+
+	/* if nothing setup the hc, we don't need to turn it off */
+	if (registers == 0)
+		return ENOTSUP;
+
+	/* map EHCI registers */
+	void *regs = as_get_mappable_page(4096);
+	ret = physmem_map((void*)(registers & PAGE_SIZE_MASK), regs, 1,
+	    AS_AREA_READ | AS_AREA_WRITE);
+	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to map registers %p:%p.\n",
+	    ret, regs, registers);
+
+	/* calculate value of BASE */
+	registers = (registers & 0xf00) | (uintptr_t)regs;
+
+	const uint32_t hcc_params =
+	    *(uint32_t*)(registers + HCC_PARAMS_OFFSET);
+	usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
+
+	/* Read value of EHCI Extended Capabilities Pointer
+	 * (points to PCI config space) */
+	uint32_t eecp =
+	    (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
+	usb_log_debug("Value of EECP: %x.\n", eecp);
+
+	/* Read the second EEC. i.e. Legacy Support and Control register */
+	/* TODO: Check capability type here */
+	ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+	    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
+	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
+	usb_log_debug("USBLEGCTLSTS: %x.\n", value);
+
+	/* Read the first EEC. i.e. Legacy Support register */
+	/* TODO: Check capability type here */
+	ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+	    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
+	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
+	usb_log_debug2("USBLEGSUP: %x.\n", value);
+
+	/* Request control from firmware/BIOS, by writing 1 to highest byte.
+	 * (OS Control semaphore)*/
+	ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+	   IPC_M_CONFIG_SPACE_WRITE_8, eecp + USBLEGSUP_OFFSET + 3, 1);
+	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to request OS EHCI control.\n",
+	    ret);
+
+	size_t wait = 0;
+	/* Wait for BIOS to release control. */
+	while ((wait < DEFAULT_WAIT) && (value & USBLEGSUP_BIOS_CONTROL)) {
+		async_usleep(WAIT_STEP);
+		ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+		    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
+		wait += WAIT_STEP;
+	}
+
+
+	if ((value & USBLEGSUP_BIOS_CONTROL) != 0) {
+		usb_log_info("BIOS released control after %d usec.\n", wait);
+	} else {
+		/* BIOS failed to hand over control, this should not happen. */
+		usb_log_warning( "BIOS failed to release control after"
+		    "%d usecs, force it.\n", wait);
+		ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+		    IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET,
+		    USBLEGSUP_OS_CONTROL);
+		CHECK_RET_HANGUP_RETURN(ret,
+		    "Failed(%d) to force OS EHCI control.\n", ret);
+		/* TODO: This does not seem to work on my machine */
+	}
+
+	/* Zero SMI enables in legacy control register.
+	 * It would prevent pre-OS code from interfering. */
+	ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+	   IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGCTLSTS_OFFSET, 0);
+	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret);
+	usb_log_debug("Zeroed USBLEGCTLSTS register.\n");
+
+	/* Read again Legacy Support and Control register */
+	ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+	    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
+	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
+	usb_log_debug2("USBLEGCTLSTS: %x.\n", value);
+
+	/* Read again Legacy Support register */
+	ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+	    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
+	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
+	usb_log_debug2("USBLEGSUP: %x.\n", value);
+
+/*
+ * TURN OFF EHCI FOR NOW, REMOVE IF THE DRIVER IS IMPLEMENTED
+ */
+
+	/* Get size of capability registers in memory space. */
+	uint8_t operation_offset = *(uint8_t*)registers;
+	usb_log_debug("USBCMD offset: %d.\n", operation_offset);
+
+	/* Zero USBCMD register. */
+	volatile uint32_t *usbcmd =
+	    (uint32_t*)((uint8_t*)registers + operation_offset + CMD_OFFSET);
+	volatile uint32_t *usbconfigured =
+	    (uint32_t*)((uint8_t*)registers + operation_offset
+	    + CONFIGFLAG_OFFSET);
+	usb_log_debug("USBCMD value: %x.\n", *usbcmd);
+	if (*usbcmd & USBCMD_RUN) {
+		*usbcmd = 0;
+		*usbconfigured = 0;
+		usb_log_info("EHCI turned off.\n");
+	} else {
+		usb_log_info("EHCI was not running.\n");
+	}
+
+	async_hangup(parent_phone);
+	return ret;
+#undef CHECK_RET_HANGUP_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
Index: uspace/drv/ehci-hcd/pci.h
===================================================================
--- uspace/drv/ehci-hcd/pci.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/ehci-hcd/pci.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,48 @@
+/*
+ * 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 drvusbehci
+ * @{
+ */
+/** @file
+ * PCI related functions needed by EHCI driver.
+ */
+#ifndef DRV_EHCI_PCI_H
+#define DRV_EHCI_PCI_H
+
+#include <ddf/driver.h>
+
+int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(ddf_dev_t *);
+int pci_disable_legacy(ddf_dev_t *);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/pciintel/pci.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -59,4 +59,5 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
+#include <pci_dev_iface.h>
 
 #include "pci.h"
@@ -93,4 +94,5 @@
   sysarg_t apic;
   sysarg_t i8259;
+
 	int irc_phone = -1;
 	int irc_service = 0;
@@ -102,10 +104,10 @@
 	}
 
-  if (irc_service) {
-    while (irc_phone < 0)
-      irc_phone = service_connect_blocking(irc_service, 0, 0);
-  } else {
+  if (irc_service == 0)
 		return false;
-	}
+
+	irc_phone = service_connect_blocking(irc_service, 0, 0);
+	if (irc_phone < 0)
+		return false;
 
 	size_t i;
@@ -113,5 +115,9 @@
 		if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
 			int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
-			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, irq);
+			int rc = async_req_1_0(irc_phone, IRC_ENABLE_INTERRUPT, irq);
+			if (rc != EOK) {
+				async_hangup(irc_phone);
+				return false;
+			}
 		}
 	}
@@ -119,4 +125,58 @@
 	async_hangup(irc_phone);
 	return true;
+}
+
+static int pci_config_space_write_32(
+    ddf_fun_t *fun, uint32_t address, uint32_t data)
+{
+	if (address > 252)
+		return EINVAL;
+	pci_conf_write_32(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_write_16(
+    ddf_fun_t *fun, uint32_t address, uint16_t data)
+{
+	if (address > 254)
+		return EINVAL;
+	pci_conf_write_16(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_write_8(
+    ddf_fun_t *fun, uint32_t address, uint8_t data)
+{
+	if (address > 255)
+		return EINVAL;
+	pci_conf_write_8(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_read_32(
+    ddf_fun_t *fun, uint32_t address, uint32_t *data)
+{
+	if (address > 252)
+		return EINVAL;
+	*data = pci_conf_read_32(PCI_FUN(fun), address);
+	return EOK;
+}
+
+static int pci_config_space_read_16(
+    ddf_fun_t *fun, uint32_t address, uint16_t *data)
+{
+	if (address > 254)
+		return EINVAL;
+	*data = pci_conf_read_16(PCI_FUN(fun), address);
+	return EOK;
+}
+
+static int pci_config_space_read_8(
+    ddf_fun_t *fun, uint32_t address, uint8_t *data)
+{
+	if (address > 255)
+		return EINVAL;
+	*data = pci_conf_read_8(PCI_FUN(fun), address);
+	return EOK;
 }
 
@@ -126,5 +186,17 @@
 };
 
-static ddf_dev_ops_t pci_fun_ops;
+static pci_dev_iface_t pci_dev_ops = {
+	.config_space_read_8 = &pci_config_space_read_8,
+	.config_space_read_16 = &pci_config_space_read_16,
+	.config_space_read_32 = &pci_config_space_read_32,
+	.config_space_write_8 = &pci_config_space_write_8,
+	.config_space_write_16 = &pci_config_space_write_16,
+	.config_space_write_32 = &pci_config_space_write_32
+};
+
+static ddf_dev_ops_t pci_fun_ops = {
+	.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
+	.interfaces[PCI_DEV_IFACE] = &pci_dev_ops
+};
 
 static int pci_add_device(ddf_dev_t *);
@@ -593,4 +665,5 @@
 {
 	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
+	pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
 }
 
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/batch.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -35,4 +35,5 @@
 #include <str_error.h>
 
+#include <usb/usb.h>
 #include <usb/debug.h>
 
@@ -46,10 +47,31 @@
 static int batch_schedule(batch_t *instance);
 
+static void batch_control(batch_t *instance,
+    usb_packet_id data_stage, usb_packet_id status_stage);
+static void batch_data(batch_t *instance, usb_packet_id pid);
 static void batch_call_in(batch_t *instance);
 static void batch_call_out(batch_t *instance);
 static void batch_call_in_and_dispose(batch_t *instance);
 static void batch_call_out_and_dispose(batch_t *instance);
-
-
+static void batch_dispose(batch_t *instance);
+
+
+/** Allocates memory and initializes internal data structures.
+ *
+ * @param[in] fun DDF function to pass to callback.
+ * @param[in] target Device and endpoint target of the transaction.
+ * @param[in] transfer_type Interrupt, Control or Bulk.
+ * @param[in] max_packet_size maximum allowed size of data packets.
+ * @param[in] speed Speed of the transaction.
+ * @param[in] buffer Data source/destination.
+ * @param[in] size Size of the buffer.
+ * @param[in] setup_buffer Setup data source (if not NULL)
+ * @param[in] setup_size Size of setup_buffer (should be always 8)
+ * @param[in] func_in function to call on inbound transaction completion
+ * @param[in] func_out function to call on outbound transaction completion
+ * @param[in] arg additional parameter to func_in or func_out
+ * @param[in] manager Pointer to toggle management structure.
+ * @return False, if there is an active TD, true otherwise.
+ */
 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
     usb_transfer_type_t transfer_type, size_t max_packet_size,
@@ -57,21 +79,29 @@
     char* setup_buffer, size_t setup_size,
     usbhc_iface_transfer_in_callback_t func_in,
-    usbhc_iface_transfer_out_callback_t func_out, void *arg)
+    usbhc_iface_transfer_out_callback_t func_out, void *arg,
+    device_keeper_t *manager
+    )
 {
 	assert(func_in == NULL || func_out == NULL);
 	assert(func_in != NULL || func_out != NULL);
 
+#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
+	if (ptr == NULL) { \
+		usb_log_error(message); \
+		if (instance) { \
+			batch_dispose(instance); \
+		} \
+		return NULL; \
+	} else (void)0
+
 	batch_t *instance = malloc(sizeof(batch_t));
-	if (instance == NULL) {
-		usb_log_error("Failed to allocate batch instance.\n");
-		return NULL;
-	}
-
-	instance->qh = queue_head_get();
-	if (instance->qh == NULL) {
-		usb_log_error("Failed to allocate queue head.\n");
-		free(instance);
-		return NULL;
-	}
+	CHECK_NULL_DISPOSE_RETURN(instance,
+	    "Failed to allocate batch instance.\n");
+	bzero(instance, sizeof(batch_t));
+
+	instance->qh = malloc32(sizeof(queue_head_t));
+	CHECK_NULL_DISPOSE_RETURN(instance->qh,
+	    "Failed to allocate batch queue head.\n");
+	queue_head_init(instance->qh);
 
 	instance->packets = (size + max_packet_size - 1) / max_packet_size;
@@ -80,50 +110,30 @@
 	}
 
-	instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets);
-	if (instance->tds == NULL) {
-		usb_log_error("Failed to allocate transfer descriptors.\n");
-		queue_head_dispose(instance->qh);
-		free(instance);
-		return NULL;
-	}
-	bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets);
-
-	const size_t transport_size = max_packet_size * instance->packets;
-
-	instance->transport_buffer =
-	   (size > 0) ? malloc32(transport_size) : NULL;
-	if ((size > 0) && (instance->transport_buffer == NULL)) {
-		usb_log_error("Failed to allocate device accessible buffer.\n");
-		queue_head_dispose(instance->qh);
-		free32(instance->tds);
-		free(instance);
-		return NULL;
-	}
-
-	instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
-	if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
-		usb_log_error("Failed to allocate device accessible setup buffer.\n");
-		queue_head_dispose(instance->qh);
-		free32(instance->tds);
-		free32(instance->transport_buffer);
-		free(instance);
-		return NULL;
-	}
-	if (instance->setup_buffer) {
+	instance->tds = malloc32(sizeof(td_t) * instance->packets);
+	CHECK_NULL_DISPOSE_RETURN(
+	    instance->tds, "Failed to allocate transfer descriptors.\n");
+	bzero(instance->tds, sizeof(td_t) * instance->packets);
+
+//	const size_t transport_size = max_packet_size * instance->packets;
+
+	if (size > 0) {
+		instance->transport_buffer = malloc32(size);
+		CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
+		    "Failed to allocate device accessible buffer.\n");
+	}
+
+	if (setup_size > 0) {
+		instance->setup_buffer = malloc32(setup_size);
+		CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
+		    "Failed to allocate device accessible setup buffer.\n");
 		memcpy(instance->setup_buffer, setup_buffer, setup_size);
 	}
 
+
+	link_initialize(&instance->link);
+
 	instance->max_packet_size = max_packet_size;
-
-	link_initialize(&instance->link);
-
 	instance->target = target;
 	instance->transfer_type = transfer_type;
-
-	if (func_out)
-		instance->callback_out = func_out;
-	if (func_in)
-		instance->callback_in = func_in;
-
 	instance->buffer = buffer;
 	instance->buffer_size = size;
@@ -132,6 +142,13 @@
 	instance->arg = arg;
 	instance->speed = speed;
-
-	queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
+	instance->manager = manager;
+
+	if (func_out)
+		instance->callback_out = func_out;
+	if (func_in)
+		instance->callback_in = func_in;
+
+	queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds));
+
 	usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
 	    instance, target.address, target.endpoint);
@@ -139,4 +156,9 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Checks batch TDs for activity.
+ *
+ * @param[in] instance Batch structure to use.
+ * @return False, if there is an active TD, true otherwise.
+ */
 bool batch_is_complete(batch_t *instance)
 {
@@ -147,154 +169,214 @@
 	size_t i = 0;
 	for (;i < instance->packets; ++i) {
-		if (transfer_descriptor_is_active(&instance->tds[i])) {
+		if (td_is_active(&instance->tds[i])) {
 			return false;
 		}
-		instance->error = transfer_descriptor_status(&instance->tds[i]);
+
+		instance->error = td_status(&instance->tds[i]);
 		if (instance->error != EOK) {
+			usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
+			    instance, i, instance->tds[i].status);
+
+			device_keeper_set_toggle(instance->manager,
+			    instance->target, td_toggle(&instance->tds[i]));
 			if (i > 0)
-				instance->transfered_size -= instance->setup_size;
-			usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
-			  instance, i, instance->tds[i].status);
+				goto substract_ret;
 			return true;
 		}
-		instance->transfered_size +=
-		    transfer_descriptor_actual_size(&instance->tds[i]);
-	}
+
+		instance->transfered_size += td_act_size(&instance->tds[i]);
+		if (td_is_short(&instance->tds[i]))
+			goto substract_ret;
+	}
+substract_ret:
 	instance->transfered_size -= instance->setup_size;
 	return true;
 }
 /*----------------------------------------------------------------------------*/
+/** Prepares control write transaction.
+ *
+ * @param[in] instance Batch structure to use.
+ */
 void batch_control_write(batch_t *instance)
 {
 	assert(instance);
-
+	/* we are data out, we are supposed to provide data */
+	memcpy(instance->transport_buffer, instance->buffer,
+	    instance->buffer_size);
+	batch_control(instance, USB_PID_OUT, USB_PID_IN);
+	instance->next_step = batch_call_out_and_dispose;
+	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares control read transaction.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void batch_control_read(batch_t *instance)
+{
+	assert(instance);
+	batch_control(instance, USB_PID_IN, USB_PID_OUT);
+	instance->next_step = batch_call_in_and_dispose;
+	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares interrupt in transaction.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void batch_interrupt_in(batch_t *instance)
+{
+	assert(instance);
+	batch_data(instance, USB_PID_IN);
+	instance->next_step = batch_call_in_and_dispose;
+	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares interrupt out transaction.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void batch_interrupt_out(batch_t *instance)
+{
+	assert(instance);
 	/* we are data out, we are supposed to provide data */
 	memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
+	batch_data(instance, USB_PID_OUT);
+	instance->next_step = batch_call_out_and_dispose;
+	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares bulk in transaction.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void batch_bulk_in(batch_t *instance)
+{
+	assert(instance);
+	batch_data(instance, USB_PID_IN);
+	instance->next_step = batch_call_in_and_dispose;
+	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares bulk out transaction.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void batch_bulk_out(batch_t *instance)
+{
+	assert(instance);
+	memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
+	batch_data(instance, USB_PID_OUT);
+	instance->next_step = batch_call_out_and_dispose;
+	usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
+	batch_schedule(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares generic data transaction
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] pid to use for data packets.
+ */
+void batch_data(batch_t *instance, usb_packet_id pid)
+{
+	assert(instance);
+	const bool low_speed = instance->speed == USB_SPEED_LOW;
+	int toggle =
+	    device_keeper_get_toggle(instance->manager, instance->target);
+	assert(toggle == 0 || toggle == 1);
+
+	size_t packet = 0;
+	size_t remain_size = instance->buffer_size;
+	while (remain_size > 0) {
+		char *data =
+		    instance->transport_buffer + instance->buffer_size
+		    - remain_size;
+
+		const size_t packet_size =
+		    (instance->max_packet_size > remain_size) ?
+		    remain_size : instance->max_packet_size;
+
+		td_t *next_packet = (packet + 1 < instance->packets)
+		    ? &instance->tds[packet + 1] : NULL;
+
+		assert(packet < instance->packets);
+		assert(packet_size <= remain_size);
+
+		td_init(
+		    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, instance->target, pid, data,
+		    next_packet);
+
+
+		toggle = 1 - toggle;
+		remain_size -= packet_size;
+		++packet;
+	}
+	device_keeper_set_toggle(instance->manager, instance->target, toggle);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares generic control transaction
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] data_stage to use for data packets.
+ * @param[in] status_stage to use for data packets.
+ */
+void batch_control(batch_t *instance,
+   usb_packet_id data_stage, usb_packet_id status_stage)
+{
+	assert(instance);
 
 	const bool low_speed = instance->speed == USB_SPEED_LOW;
 	int toggle = 0;
 	/* setup stage */
-	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
-	    instance->setup_size, toggle, false, low_speed,
-	    instance->target, USB_PID_SETUP, instance->setup_buffer,
-	    &instance->tds[1]);
-
-	/* data stage */
-	size_t i = 1;
-	for (;i < instance->packets - 1; ++i) {
-		char *data =
-		    instance->transport_buffer + ((i - 1) * instance->max_packet_size);
-		toggle = 1 - toggle;
-
-		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
-		    instance->max_packet_size, toggle++, false, low_speed,
-		    instance->target, USB_PID_OUT, data, &instance->tds[i + 1]);
-	}
-
-	/* status stage */
-	i = instance->packets - 1;
-	transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
-	    0, 1, false, low_speed, instance->target, USB_PID_IN, NULL, NULL);
-
-	instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
-	usb_log_debug2("Control write last TD status: %x.\n",
-		instance->tds[i].status);
-
-	instance->next_step = batch_call_out_and_dispose;
-	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
-	batch_schedule(instance);
-}
-/*----------------------------------------------------------------------------*/
-void batch_control_read(batch_t *instance)
-{
-	assert(instance);
-
-	const bool low_speed = instance->speed == USB_SPEED_LOW;
-	int toggle = 0;
-	/* setup stage */
-	transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT,
+	td_init(instance->tds, DEFAULT_ERROR_COUNT,
 	    instance->setup_size, toggle, false, low_speed, instance->target,
 	    USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]);
 
 	/* data stage */
-	size_t i = 1;
-	for (;i < instance->packets - 1; ++i) {
+	size_t packet = 1;
+	size_t remain_size = instance->buffer_size;
+	while (remain_size > 0) {
 		char *data =
-		    instance->transport_buffer + ((i - 1) * instance->max_packet_size);
+		    instance->transport_buffer + instance->buffer_size
+		    - remain_size;
+
 		toggle = 1 - toggle;
 
-		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
-		    instance->max_packet_size, toggle, false, low_speed,
-				instance->target, USB_PID_IN, data, &instance->tds[i + 1]);
+		const size_t packet_size =
+		    (instance->max_packet_size > remain_size) ?
+		    remain_size : instance->max_packet_size;
+
+		td_init(
+		    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, instance->target, data_stage,
+		    data, &instance->tds[packet + 1]);
+
+		++packet;
+		assert(packet < instance->packets);
+		assert(packet_size <= remain_size);
+		remain_size -= packet_size;
 	}
 
 	/* status stage */
-	i = instance->packets - 1;
-	transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
-	    0, 1, false, low_speed, instance->target, USB_PID_OUT, NULL, NULL);
-
-	instance->tds[i].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
-	usb_log_debug2("Control read last TD status: %x.\n",
-		instance->tds[i].status);
-
-	instance->next_step = batch_call_in_and_dispose;
-	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
-	batch_schedule(instance);
-}
-/*----------------------------------------------------------------------------*/
-void batch_interrupt_in(batch_t *instance)
-{
-	assert(instance);
-
-	const bool low_speed = instance->speed == USB_SPEED_LOW;
-	int toggle = 1;
-	size_t i = 0;
-	for (;i < instance->packets; ++i) {
-		char *data =
-		    instance->transport_buffer + (i  * instance->max_packet_size);
-		transfer_descriptor_t *next = (i + 1) < instance->packets ?
-		    &instance->tds[i + 1] : NULL;
-		toggle = 1 - toggle;
-
-		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
-		    instance->max_packet_size, toggle, false, low_speed,
-		    instance->target, USB_PID_IN, data, next);
-	}
-
-	instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
-
-	instance->next_step = batch_call_in_and_dispose;
-	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
-	batch_schedule(instance);
-}
-/*----------------------------------------------------------------------------*/
-void batch_interrupt_out(batch_t *instance)
-{
-	assert(instance);
-
-	memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
-
-	const bool low_speed = instance->speed == USB_SPEED_LOW;
-	int toggle = 1;
-	size_t i = 0;
-	for (;i < instance->packets; ++i) {
-		char *data =
-		    instance->transport_buffer + (i  * instance->max_packet_size);
-		transfer_descriptor_t *next = (i + 1) < instance->packets ?
-		    &instance->tds[i + 1] : NULL;
-		toggle = 1 - toggle;
-
-		transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT,
-		    instance->max_packet_size, toggle++, false, low_speed,
-		    instance->target, USB_PID_OUT, data, next);
-	}
-
-	instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
-
-	instance->next_step = batch_call_out_and_dispose;
-	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
-	batch_schedule(instance);
-}
-/*----------------------------------------------------------------------------*/
+	assert(packet == instance->packets - 1);
+	td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,
+	    0, 1, false, low_speed, instance->target, status_stage, NULL, NULL);
+
+
+	instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
+	usb_log_debug2("Control last TD status: %x.\n",
+	    instance->tds[packet].status);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares data, gets error status and calls callback in.
+ *
+ * @param[in] instance Batch structure to use.
+ */
 void batch_call_in(batch_t *instance)
 {
@@ -302,5 +384,7 @@
 	assert(instance->callback_in);
 
-	memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
+	/* we are data in, we need data */
+	memcpy(instance->buffer, instance->transport_buffer,
+	    instance->buffer_size);
 
 	int err = instance->error;
@@ -309,9 +393,12 @@
 	    instance->transfered_size);
 
-	instance->callback_in(instance->fun,
-	    err, instance->transfered_size,
-	    instance->arg);
-}
-/*----------------------------------------------------------------------------*/
+	instance->callback_in(
+	    instance->fun, err, instance->transfered_size, instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+/** Gets error status and calls callback out.
+ *
+ * @param[in] instance Batch structure to use.
+ */
 void batch_call_out(batch_t *instance)
 {
@@ -326,9 +413,35 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Prepares data, gets error status, calls callback in and dispose.
+ *
+ * @param[in] instance Batch structure to use.
+ */
 void batch_call_in_and_dispose(batch_t *instance)
 {
 	assert(instance);
 	batch_call_in(instance);
+	batch_dispose(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Gets error status, calls callback out and dispose.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void batch_call_out_and_dispose(batch_t *instance)
+{
+	assert(instance);
+	batch_call_out(instance);
+	batch_dispose(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Correctly disposes all used data structures.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void batch_dispose(batch_t *instance)
+{
+	assert(instance);
 	usb_log_debug("Batch(%p) disposing.\n", instance);
+	/* free32 is NULL safe */
 	free32(instance->tds);
 	free32(instance->qh);
@@ -338,16 +451,4 @@
 }
 /*----------------------------------------------------------------------------*/
-void batch_call_out_and_dispose(batch_t *instance)
-{
-	assert(instance);
-	batch_call_out(instance);
-	usb_log_debug("Batch(%p) disposing.\n", instance);
-	free32(instance->tds);
-	free32(instance->qh);
-	free32(instance->setup_buffer);
-	free32(instance->transport_buffer);
-	free(instance);
-}
-/*----------------------------------------------------------------------------*/
 int batch_schedule(batch_t *instance)
 {
Index: uspace/drv/uhci-hcd/batch.h
===================================================================
--- uspace/drv/uhci-hcd/batch.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/batch.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -42,4 +42,5 @@
 #include "uhci_struct/transfer_descriptor.h"
 #include "uhci_struct/queue_head.h"
+#include "utils/device_keeper.h"
 
 typedef struct batch
@@ -65,6 +66,7 @@
 	ddf_fun_t *fun;
 	queue_head_t *qh;
-	transfer_descriptor_t *tds;
+	td_t *tds;
 	void (*next_step)(struct batch*);
+	device_keeper_t *manager;
 } batch_t;
 
@@ -74,5 +76,7 @@
 		char *setup_buffer, size_t setup_size,
     usbhc_iface_transfer_in_callback_t func_in,
-    usbhc_iface_transfer_out_callback_t func_out, void *arg);
+    usbhc_iface_transfer_out_callback_t func_out, void *arg,
+		device_keeper_t *manager
+		);
 
 bool batch_is_complete(batch_t *instance);
@@ -86,14 +90,7 @@
 void batch_interrupt_out(batch_t *instance);
 
-/* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */
-void batch_control_setup_old(batch_t *instance);
+void batch_bulk_in(batch_t *instance);
 
-void batch_control_write_data_old(batch_t *instance);
-
-void batch_control_read_data_old(batch_t *instance);
-
-void batch_control_write_status_old(batch_t *instance);
-
-void batch_control_read_status_old(batch_t *instance);
+void batch_bulk_out(batch_t *instance);
 #endif
 /**
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/iface.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -43,4 +43,10 @@
 #include "utils/device_keeper.h"
 
+/** Reserve default address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] speed Speed to associate with the new default address.
+ * @return Error code.
+ */
 /*----------------------------------------------------------------------------*/
 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
@@ -54,4 +60,9 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Release default address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @return Error code.
+ */
 static int release_default_address(ddf_fun_t *fun)
 {
@@ -64,4 +75,11 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Request address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] speed Speed to associate with the new default address.
+ * @param[out] address Place to write a new address.
+ * @return Error code.
+ */
 static int request_address(ddf_fun_t *fun, usb_speed_t speed,
     usb_address_t *address)
@@ -80,4 +98,11 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Bind address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address of the device
+ * @param[in] handle Devman handle of the device driver.
+ * @return Error code.
+ */
 static int bind_address(
   ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
@@ -91,4 +116,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Release address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
 static int release_address(ddf_fun_t *fun, usb_address_t address)
 {
@@ -101,4 +132,15 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Interrupt out transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] max_packet_size maximum size of data packet the device accepts
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
 static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
     size_t max_packet_size, void *data, size_t size,
@@ -114,5 +156,6 @@
 
 	batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
-	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg);
+	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
+	    &hc->device_manager);
 	if (!batch)
 		return ENOMEM;
@@ -121,4 +164,15 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Interrupt in transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] max_packet_size maximum size of data packet the device accepts
+ * @param[out] data Data destination.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
 static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
     size_t max_packet_size, void *data, size_t size,
@@ -133,5 +187,6 @@
 
 	batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT,
-	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg);
+	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
+			&hc->device_manager);
 	if (!batch)
 		return ENOMEM;
@@ -140,4 +195,80 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Bulk out transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] max_packet_size maximum size of data packet the device accepts
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int bulk_out(ddf_fun_t *fun, usb_target_t target,
+    size_t max_packet_size, void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
+
+	usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
+	    max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg,
+	    &hc->device_manager);
+	if (!batch)
+		return ENOMEM;
+	batch_bulk_out(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Bulk in transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] max_packet_size maximum size of data packet the device accepts
+ * @param[out] data Data destination.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int bulk_in(ddf_fun_t *fun, usb_target_t target,
+    size_t max_packet_size, void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	assert(fun);
+	uhci_t *hc = fun_to_uhci(fun);
+	assert(hc);
+	usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address);
+	usb_log_debug("Bulk IN %d:%d %zu(%zu).\n",
+	    target.address, target.endpoint, size, max_packet_size);
+
+	batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK,
+	    max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg,
+	    &hc->device_manager);
+	if (!batch)
+		return ENOMEM;
+	batch_bulk_in(batch);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Control write transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] max_packet_size maximum size of data packet the device accepts.
+ * @param[in] setup_data Data to send with SETUP packet.
+ * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion.
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
 static int control_write(ddf_fun_t *fun, usb_target_t target,
     size_t max_packet_size,
@@ -152,13 +283,30 @@
 	    target.address, target.endpoint, size, max_packet_size);
 
+	if (setup_size != 8)
+		return EINVAL;
+
 	batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
 	    max_packet_size, speed, data, size, setup_data, setup_size,
-	    NULL, callback, arg);
-	if (!batch)
-		return ENOMEM;
+	    NULL, callback, arg, &hc->device_manager);
+	if (!batch)
+		return ENOMEM;
+	device_keeper_reset_if_need(&hc->device_manager, target, setup_data);
 	batch_control_write(batch);
 	return EOK;
 }
 /*----------------------------------------------------------------------------*/
+/** Control read transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] max_packet_size maximum size of data packet the device accepts.
+ * @param[in] setup_data Data to send with SETUP packet.
+ * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
+ * @param[out] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion.
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
 static int control_read(ddf_fun_t *fun, usb_target_t target,
     size_t max_packet_size,
@@ -175,5 +323,5 @@
 	batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL,
 	    max_packet_size, speed, data, size, setup_data, setup_size, callback,
-	    NULL, arg);
+	    NULL, arg, &hc->device_manager);
 	if (!batch)
 		return ENOMEM;
@@ -181,6 +329,4 @@
 	return EOK;
 }
-
-
 /*----------------------------------------------------------------------------*/
 usbhc_iface_t uhci_iface = {
@@ -194,4 +340,7 @@
 	.interrupt_in = interrupt_in,
 
+	.bulk_in = bulk_in,
+	.bulk_out = bulk_out,
+
 	.control_read = control_read,
 	.control_write = control_write,
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -34,10 +34,10 @@
 #include <ddf/driver.h>
 #include <ddf/interrupt.h>
+#include <device/hw_res.h>
+#include <errno.h>
+#include <str_error.h>
+
 #include <usb_iface.h>
 #include <usb/ddfiface.h>
-#include <device/hw_res.h>
-
-#include <errno.h>
-
 #include <usb/debug.h>
 
@@ -50,5 +50,4 @@
 
 static int uhci_add_device(ddf_dev_t *device);
-
 /*----------------------------------------------------------------------------*/
 static driver_ops_t uhci_driver_ops = {
@@ -61,4 +60,10 @@
 };
 /*----------------------------------------------------------------------------*/
+/** IRQ handling callback, identifies devic
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
 {
@@ -70,13 +75,23 @@
 }
 /*----------------------------------------------------------------------------*/
-#define CHECK_RET_RETURN(ret, message...) \
+/** Initializes a new ddf driver instance of UHCI hcd.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ *
+ * Gets and initialies hardware resources, disables any legacy support,
+ * and reports root hub device.
+ */
+int uhci_add_device(ddf_dev_t *device)
+{
+	assert(device);
+	uhci_t *hcd = NULL;
+#define CHECK_RET_FREE_HC_RETURN(ret, message...) \
 if (ret != EOK) { \
 	usb_log_error(message); \
+	if (hcd != NULL) \
+		free(hcd); \
 	return ret; \
 }
-
-static int uhci_add_device(ddf_dev_t *device)
-{
-	assert(device);
 
 	usb_log_info("uhci_add_device() called\n");
@@ -88,60 +103,77 @@
 	int ret =
 	    pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
-
-	CHECK_RET_RETURN(ret,
+	CHECK_RET_FREE_HC_RETURN(ret,
 	    "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
 	usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
 	    io_reg_base, io_reg_size, irq);
 
-//	ret = pci_enable_interrupts(device);
-//	CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret);
+	ret = pci_disable_legacy(device);
+	CHECK_RET_FREE_HC_RETURN(ret,
+	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
 
-	uhci_t *uhci_hc = malloc(sizeof(uhci_t));
-	ret = (uhci_hc != NULL) ? EOK : ENOMEM;
-	CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n");
+#if 0
+	ret = pci_enable_interrupts(device);
+	if (ret != EOK) {
+		usb_log_warning(
+		    "Failed(%d) to enable interrupts, fall back to polling.\n",
+		    ret);
+	}
+#endif
 
-	ret = uhci_init(uhci_hc, device, (void*)io_reg_base, io_reg_size);
-	if (ret != EOK) {
-		usb_log_error("Failed to init uhci-hcd.\n");
-		free(uhci_hc);
-		return ret;
-	}
+	hcd = malloc(sizeof(uhci_t));
+	ret = (hcd != NULL) ? EOK : ENOMEM;
+	CHECK_RET_FREE_HC_RETURN(ret,
+	    "Failed(%d) to allocate memory for uhci hcd.\n", ret);
+
+	ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
+	CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
+#undef CHECK_RET_FREE_HC_RETURN
 
 	/*
-	 * We might free uhci_hc, but that does not matter since no one
+	 * We might free hcd, but that does not matter since no one
 	 * else would access driver_data anyway.
 	 */
-	device->driver_data = uhci_hc;
+	device->driver_data = hcd;
+
+	ddf_fun_t *rh = NULL;
+#define CHECK_RET_FINI_FREE_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	if (hcd != NULL) {\
+		uhci_fini(hcd); \
+		free(hcd); \
+	} \
+	if (rh != NULL) \
+		free(rh); \
+	return ret; \
+}
+
+	/* It does no harm if we register this on polling */
 	ret = register_interrupt_handler(device, irq, irq_handler,
-	    &uhci_hc->interrupt_code);
-	if (ret != EOK) {
-		usb_log_error("Failed to register interrupt handler.\n");
-		uhci_fini(uhci_hc);
-		free(uhci_hc);
-		return ret;
-	}
+	    &hcd->interrupt_code);
+	CHECK_RET_FINI_FREE_RETURN(ret,
+	    "Failed(%d) to register interrupt handler.\n", ret);
 
-	ddf_fun_t *rh;
 	ret = setup_root_hub(&rh, device);
-	if (ret != EOK) {
-		usb_log_error("Failed to setup uhci root hub.\n");
-		uhci_fini(uhci_hc);
-		free(uhci_hc);
-		return ret;
-	}
-	rh->driver_data = uhci_hc->ddf_instance;
+	CHECK_RET_FINI_FREE_RETURN(ret,
+	    "Failed(%d) to setup UHCI root hub.\n", ret);
+	rh->driver_data = hcd->ddf_instance;
 
 	ret = ddf_fun_bind(rh);
-	if (ret != EOK) {
-		usb_log_error("Failed to register root hub.\n");
-		uhci_fini(uhci_hc);
-		free(uhci_hc);
-		free(rh);
-		return ret;
-	}
+	CHECK_RET_FINI_FREE_RETURN(ret,
+	    "Failed(%d) to register UHCI root hub.\n", ret);
 
 	return EOK;
+#undef CHECK_RET_FINI_FREE_RETURN
 }
 /*----------------------------------------------------------------------------*/
+/** Initializes global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
 int main(int argc, char *argv[])
 {
Index: uspace/drv/uhci-hcd/pci.c
===================================================================
--- uspace/drv/uhci-hcd/pci.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/pci.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -40,4 +40,5 @@
 
 #include <usb/debug.h>
+#include <pci_dev_iface.h>
 
 #include "pci.h"
@@ -64,5 +65,4 @@
 
 	int rc;
-
 	hw_resource_list_t hw_resources;
 	rc = hw_res_get_resource_list(parent_phone, &hw_resources);
@@ -81,28 +81,25 @@
 	for (i = 0; i < hw_resources.count; i++) {
 		hw_resource_t *res = &hw_resources.resources[i];
-		switch (res->type) {
-			case INTERRUPT:
-				irq = res->res.interrupt.irq;
-				irq_found = true;
-				usb_log_debug2("Found interrupt: %d.\n", irq);
-				break;
-			case IO_RANGE:
-				io_address = res->res.io_range.address;
-				io_size = res->res.io_range.size;
-				usb_log_debug2("Found io: %llx %zu.\n",
-				    res->res.io_range.address, res->res.io_range.size);
-				io_found = true;
-				break;
-			default:
-				break;
+		switch (res->type)
+		{
+		case INTERRUPT:
+			irq = res->res.interrupt.irq;
+			irq_found = true;
+			usb_log_debug2("Found interrupt: %d.\n", irq);
+			break;
+
+		case IO_RANGE:
+			io_address = res->res.io_range.address;
+			io_size = res->res.io_range.size;
+			usb_log_debug2("Found io: %llx %zu.\n",
+			    res->res.io_range.address, res->res.io_range.size);
+			io_found = true;
+
+		default:
+			break;
 		}
 	}
 
-	if (!io_found) {
-		rc = ENOENT;
-		goto leave;
-	}
-
-	if (!irq_found) {
+	if (!io_found || !irq_found) {
 		rc = ENOENT;
 		goto leave;
@@ -120,4 +117,9 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Calls the PCI driver with a request to enable interrupts
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
 int pci_enable_interrupts(ddf_dev_t *device)
 {
@@ -128,4 +130,31 @@
 	return enabled ? EOK : EIO;
 }
+/*----------------------------------------------------------------------------*/
+/** Calls the PCI driver with a request to clear legacy support register
+ *
+ * @param[in] device Device asking to disable interrupts
+ * @return Error code.
+ */
+int pci_disable_legacy(ddf_dev_t *device)
+{
+	assert(device);
+	int parent_phone =
+	    devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	/* See UHCI design guide for these values,
+	 * write all WC bits in USB legacy register */
+	sysarg_t address = 0xc0;
+	sysarg_t value = 0x8f00;
+
+	int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
+	    IPC_M_CONFIG_SPACE_WRITE_16, address, value);
+	async_hangup(parent_phone);
+
+	return rc;
+}
+/*----------------------------------------------------------------------------*/
 /**
  * @}
Index: uspace/drv/uhci-hcd/pci.h
===================================================================
--- uspace/drv/uhci-hcd/pci.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/pci.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -40,4 +40,5 @@
 int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
 int pci_enable_interrupts(ddf_dev_t *);
+int pci_disable_legacy(ddf_dev_t *);
 
 #endif
Index: uspace/drv/uhci-hcd/root_hub.c
===================================================================
--- uspace/drv/uhci-hcd/root_hub.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/root_hub.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -45,7 +45,14 @@
 
 /*----------------------------------------------------------------------------*/
-static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
-    devman_handle_t *handle)
+/** Gets handle of the respective hc (parent device).
+ *
+ * @param[in] root_hub_fun Root hub function seeking hc handle.
+ * @param[out] handle Place to write the handle.
+ * @return Error code.
+ */
+static int usb_iface_get_hc_handle_rh_impl(
+    ddf_fun_t *root_hub_fun, devman_handle_t *handle)
 {
+	/* TODO: Can't this use parent pointer? */
 	ddf_fun_t *hc_fun = root_hub_fun->driver_data;
 	assert(hc_fun != NULL);
@@ -56,7 +63,16 @@
 }
 /*----------------------------------------------------------------------------*/
-static int usb_iface_get_address_rh_impl(ddf_fun_t *fun, devman_handle_t handle,
-    usb_address_t *address)
+/** Gets USB address of the calling device.
+ *
+ * @param[in] fun Root hub function.
+ * @param[in] handle Handle of the device seeking address.
+ * @param[out] address Place to store found address.
+ * @return Error code.
+ */
+static int usb_iface_get_address_rh_impl(
+    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
 {
+	/* TODO: What does this do? Is it neccessary? Can't it use implemented
+	 * hc function?*/
 	assert(fun);
 	ddf_fun_t *hc_fun = fun->driver_data;
@@ -65,6 +81,5 @@
 	assert(hc);
 
-	usb_address_t addr = device_keeper_find(&hc->device_manager,
-	    handle);
+	usb_address_t addr = device_keeper_find(&hc->device_manager, handle);
 	if (addr < 0) {
 		return addr;
@@ -83,4 +98,9 @@
 };
 /*----------------------------------------------------------------------------*/
+/** Gets root hub hw resources.
+ *
+ * @param[in] fun Root hub function.
+ * @return Pointer to the resource list used by the root hub.
+ */
 static hw_resource_list_t *get_resource_list(ddf_fun_t *dev)
 {
@@ -91,5 +111,5 @@
 	assert(hc);
 
-	//TODO: fix memory leak
+	/* TODO: fix memory leak */
 	hw_resource_list_t *resource_list = malloc(sizeof(hw_resource_list_t));
 	assert(resource_list);
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -38,4 +38,15 @@
 #include "transfer_list.h"
 
+static void transfer_list_remove_batch(
+    transfer_list_t *instance, batch_t *batch);
+/*----------------------------------------------------------------------------*/
+/** Initializes transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ * @param[in] name Name of te new list.
+ * @return Error code
+ *
+ * Allocates memory for internat queue_head_t structure.
+ */
 int transfer_list_init(transfer_list_t *instance, const char *name)
 {
@@ -43,10 +54,10 @@
 	instance->next = NULL;
 	instance->name = name;
-	instance->queue_head = queue_head_get();
+	instance->queue_head = malloc32(sizeof(queue_head_t));
 	if (!instance->queue_head) {
 		usb_log_error("Failed to allocate queue head.\n");
 		return ENOMEM;
 	}
-	instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);
+	instance->queue_head_pa = addr_to_phys(instance->queue_head);
 
 	queue_head_init(instance->queue_head);
@@ -56,4 +67,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Set the next list in chain.
+ *
+ * @param[in] instance List to lead.
+ * @param[in] next List to append.
+ * @return Error code
+ */
 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
 {
@@ -66,9 +83,16 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Submits a new transfer batch to list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] batch Transfer batch to submit.
+ * @return Error code
+ */
 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
 {
 	assert(instance);
 	assert(batch);
-	usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name);
+	usb_log_debug2(
+	    "Adding batch(%p) to queue %s.\n", batch, instance->name);
 
 	uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
@@ -97,11 +121,17 @@
 	queue_head_append_qh(last->qh, pa);
 	list_append(&batch->link, &instance->batch_list);
+
 	usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
-		batch, instance->name, first );
+		batch, instance->name, first);
 	fibril_mutex_unlock(&instance->guard);
 }
 /*----------------------------------------------------------------------------*/
-static void transfer_list_remove_batch(
-    transfer_list_t *instance, batch_t *batch)
+/** Removes a transfer batch from list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] batch Transfer batch to remove.
+ * @return Error code
+ */
+void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
 {
 	assert(instance);
@@ -109,15 +139,19 @@
 	assert(instance->queue_head);
 	assert(batch->qh);
-	usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name);
+	usb_log_debug2(
+	    "Removing batch(%p) from queue %s.\n", batch, instance->name);
 
-	/* I'm the first one here */
 	if (batch->link.prev == &instance->batch_list) {
-		usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n",
-			batch, instance->name, batch->qh->next_queue);
+		/* I'm the first one here */
+		usb_log_debug(
+		    "Batch(%p) removed (FIRST) from %s, next element %x.\n",
+		    batch, instance->name, batch->qh->next_queue);
 		instance->queue_head->element = batch->qh->next_queue;
 	} else {
-		usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n",
-			batch, instance->name, batch->qh->next_queue);
-		batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
+		usb_log_debug(
+		    "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n",
+		    batch, instance->name, batch->qh->next_queue);
+		batch_t *prev =
+		    list_get_instance(batch->link.prev, batch_t, link);
 		prev->qh->next_queue = batch->qh->next_queue;
 	}
@@ -125,4 +159,9 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Checks list for finished transfers.
+ *
+ * @param[in] instance List to use.
+ * @return Error code
+ */
 void transfer_list_remove_finished(transfer_list_t *instance)
 {
Index: uspace/drv/uhci-hcd/transfer_list.h
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/transfer_list.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -58,5 +58,5 @@
 {
 	assert(instance);
-	queue_head_dispose(instance->queue_head);
+	free32(instance->queue_head);
 }
 void transfer_list_remove_finished(transfer_list_t *instance);
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -61,6 +61,13 @@
 };
 
-static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle,
-    usb_address_t *address)
+/** Gets USB address of the calling device.
+ *
+ * @param[in] fun UHCI hc function.
+ * @param[in] handle Handle of the device seeking address.
+ * @param[out] address Place to store found address.
+ * @return Error code.
+ */
+static int usb_iface_get_address(
+    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
 {
 	assert(fun);
@@ -90,5 +97,5 @@
 	.interfaces[USBHC_DEV_IFACE] = &uhci_iface,
 };
-
+/*----------------------------------------------------------------------------*/
 static int uhci_init_transfer_lists(uhci_t *instance);
 static int uhci_init_mem_structures(uhci_t *instance);
@@ -99,7 +106,15 @@
 
 static bool allowed_usb_packet(
-	bool low_speed, usb_transfer_type_t, size_t size);
-
-
+    bool low_speed, usb_transfer_type_t transfer, size_t size);
+/*----------------------------------------------------------------------------*/
+/** Initializes UHCI hcd driver structure
+ *
+ * @param[in] instance Memory place to initialize.
+ * @param[in] dev DDF device.
+ * @param[in] regs Address of I/O control registers.
+ * @param[in] size Size of I/O control registers.
+ * @return Error code.
+ * @note Should be called only once on any structure.
+ */
 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
 {
@@ -115,10 +130,9 @@
 	} else (void) 0
 
-	/*
-	 * Create UHCI function.
-	 */
+	/* Create UHCI function. */
 	instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
 	ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
-	CHECK_RET_DEST_FUN_RETURN(ret, "Failed to create UHCI device function.\n");
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed to create UHCI device function.\n");
 
 	instance->ddf_instance->ops = &uhci_ops;
@@ -126,5 +140,6 @@
 
 	ret = ddf_fun_bind(instance->ddf_instance);
-	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to bind UHCI device function: %s.\n",
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to bind UHCI device function: %s.\n",
 	    ret, str_error(ret));
 
@@ -132,15 +147,18 @@
 	regs_t *io;
 	ret = pio_enable(regs, reg_size, (void**)&io);
-	CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to gain access to registers at %p: %s.\n",
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed(%d) to gain access to registers at %p: %s.\n",
 	    ret, str_error(ret), io);
 	instance->registers = io;
-	usb_log_debug("Device registers at %p(%u) accessible.\n", io, reg_size);
+	usb_log_debug("Device registers at %p(%u) accessible.\n",
+	    io, reg_size);
 
 	ret = uhci_init_mem_structures(instance);
-	CHECK_RET_DEST_FUN_RETURN(ret, "Failed to initialize UHCI memory structures.\n");
+	CHECK_RET_DEST_FUN_RETURN(ret,
+	    "Failed to initialize UHCI memory structures.\n");
 
 	uhci_init_hw(instance);
-
-	instance->cleaner = fibril_create(uhci_interrupt_emulator, instance);
+	instance->cleaner =
+	    fibril_create(uhci_interrupt_emulator, instance);
 	fibril_add_ready(instance->cleaner);
 
@@ -153,29 +171,46 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Initializes UHCI hcd hw resources.
+ *
+ * @param[in] instance UHCI structure to use.
+ */
 void uhci_init_hw(uhci_t *instance)
 {
-	/* reset everything, who knows what touched it before us */
-	pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
+	assert(instance);
+	regs_t *registers = instance->registers;
+
+	/* Reset everything, who knows what touched it before us */
+	pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
 	async_usleep(10000); /* 10ms according to USB spec */
-	pio_write_16(&instance->registers->usbcmd, 0);
-
-	/* reset hc, all states and counters */
-	pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET);
-	while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0)
-		{ async_usleep(10); }
-
-	/* set framelist pointer */
+	pio_write_16(&registers->usbcmd, 0);
+
+	/* Reset hc, all states and counters */
+	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
+	do { async_usleep(10); }
+	while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
+
+	/* Set framelist pointer */
 	const uint32_t pa = addr_to_phys(instance->frame_list);
-	pio_write_32(&instance->registers->flbaseadd, pa);
-
-	/* enable all interrupts, but resume interrupt */
-	pio_write_16(&instance->registers->usbintr,
-		  UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
+	pio_write_32(&registers->flbaseadd, pa);
+
+	/* Enable all interrupts, but resume interrupt */
+//	pio_write_16(&instance->registers->usbintr,
+//	    UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
+
+	uint16_t status = pio_read_16(&registers->usbcmd);
+	if (status != 0)
+		usb_log_warning("Previous command value: %x.\n", status);
 
 	/* Start the hc with large(64B) packet FSBR */
-	pio_write_16(&instance->registers->usbcmd,
+	pio_write_16(&registers->usbcmd,
 	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
 }
 /*----------------------------------------------------------------------------*/
+/** Initializes UHCI hcd memory structures.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @return Error code
+ * @note Should be called only once on any structure.
+ */
 int uhci_init_mem_structures(uhci_t *instance)
 {
@@ -189,24 +224,27 @@
 	} else (void) 0
 
-	/* init interrupt code */
+	/* Init interrupt code */
 	instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
 	int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
-	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n");
+	CHECK_RET_DEST_CMDS_RETURN(ret,
+	    "Failed to allocate interrupt cmds space.\n");
 
 	{
 		irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
 		memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
-		interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
-		interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
+		interrupt_commands[0].addr =
+		    (void*)&instance->registers->usbsts;
+		interrupt_commands[1].addr =
+		    (void*)&instance->registers->usbsts;
 		instance->interrupt_code.cmdcount =
-				sizeof(uhci_cmds) / sizeof(irq_cmd_t);
-	}
-
-	/* init transfer lists */
+		    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
+	}
+
+	/* Init transfer lists */
 	ret = uhci_init_transfer_lists(instance);
-	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n");
+	CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
 	usb_log_debug("Initialized transfer lists.\n");
 
-	/* frame list initialization */
+	/* Init USB frame list page*/
 	instance->frame_list = get_page();
 	ret = instance ? EOK : ENOMEM;
@@ -214,5 +252,5 @@
 	usb_log_debug("Initialized frame list.\n");
 
-	/* initialize all frames to point to the first queue head */
+	/* Set all frames to point to the first queue head */
 	const uint32_t queue =
 	  instance->transfers_interrupt.queue_head_pa
@@ -224,5 +262,5 @@
 	}
 
-	/* init address keeper(libusb) */
+	/* Init device keeper*/
 	device_keeper_init(&instance->device_manager);
 	usb_log_debug("Initialized device manager.\n");
@@ -232,4 +270,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Initializes UHCI hcd transfer lists.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @return Error code
+ * @note Should be called only once on any structure.
+ */
 int uhci_init_transfer_lists(uhci_t *instance)
 {
@@ -249,8 +293,13 @@
 	ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
 	CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
-	ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
+
+	ret = transfer_list_init(
+	    &instance->transfers_control_full, "CONTROL_FULL");
 	CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
-	ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
+
+	ret = transfer_list_init(
+	    &instance->transfers_control_slow, "CONTROL_SLOW");
 	CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
+
 	ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
 	CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
@@ -269,13 +318,14 @@
 #endif
 
-	instance->transfers[0][USB_TRANSFER_INTERRUPT] =
+	/* Assign pointers to be used during scheduling */
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
 	  &instance->transfers_interrupt;
-	instance->transfers[1][USB_TRANSFER_INTERRUPT] =
+	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
 	  &instance->transfers_interrupt;
-	instance->transfers[0][USB_TRANSFER_CONTROL] =
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
 	  &instance->transfers_control_full;
-	instance->transfers[1][USB_TRANSFER_CONTROL] =
+	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
 	  &instance->transfers_control_slow;
-	instance->transfers[0][USB_TRANSFER_BULK] =
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
 	  &instance->transfers_bulk_full;
 
@@ -284,4 +334,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Schedules batch for execution.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] batch Transfer batch to schedule.
+ * @return Error code
+ */
 int uhci_schedule(uhci_t *instance, batch_t *batch)
 {
@@ -291,6 +347,7 @@
 	if (!allowed_usb_packet(
 	    low_speed, batch->transfer_type, batch->max_packet_size)) {
-		usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
-			  low_speed ? "LOW" : "FULL" , batch->transfer_type,
+		usb_log_warning(
+		    "Invalid USB packet specified %s SPEED %d %zu.\n",
+		    low_speed ? "LOW" : "FULL" , batch->transfer_type,
 		    batch->max_packet_size);
 		return ENOTSUP;
@@ -306,10 +363,13 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Takes action based on the interrupt cause.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] status Value of the stsatus regiser at the time of interrupt.
+ */
 void uhci_interrupt(uhci_t *instance, uint16_t status)
 {
 	assert(instance);
-//	if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
-//		return;
-//	usb_log_debug2("UHCI interrupt: %X.\n", status);
+	/* TODO: Check interrupt cause here */
 	transfer_list_remove_finished(&instance->transfers_interrupt);
 	transfer_list_remove_finished(&instance->transfers_control_slow);
@@ -318,4 +378,9 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Polling function, emulates interrupts.
+ *
+ * @param[in] arg UHCI structure to use.
+ * @return EOK
+ */
 int uhci_interrupt_emulator(void* arg)
 {
@@ -331,17 +396,28 @@
 		uhci_interrupt(instance, status);
 		pio_write_16(&instance->registers->usbsts, 0x1f);
-		async_usleep(UHCI_CLEANER_TIMEOUT * 5);
+		async_usleep(UHCI_CLEANER_TIMEOUT);
 	}
 	return EOK;
 }
 /*---------------------------------------------------------------------------*/
+/** Debug function, checks consistency of memory structures.
+ *
+ * @param[in] arg UHCI structure to use.
+ * @return EOK
+ */
 int uhci_debug_checker(void *arg)
 {
 	uhci_t *instance = (uhci_t*)arg;
 	assert(instance);
+
+#define QH(queue) \
+	instance->transfers_##queue.queue_head
+
 	while (1) {
 		const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
 		const uint16_t sts = pio_read_16(&instance->registers->usbsts);
-		const uint16_t intr = pio_read_16(&instance->registers->usbintr);
+		const uint16_t intr =
+		    pio_read_16(&instance->registers->usbintr);
+
 		if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
 			usb_log_debug2("Command: %X Status: %X Intr: %x\n",
@@ -353,58 +429,64 @@
 		if (frame_list != addr_to_phys(instance->frame_list)) {
 			usb_log_debug("Framelist address: %p vs. %p.\n",
-				frame_list, addr_to_phys(instance->frame_list));
-		}
+			    frame_list, addr_to_phys(instance->frame_list));
+		}
+
 		int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
 		usb_log_debug2("Framelist item: %d \n", frnum );
 
-		queue_head_t* qh = instance->transfers_interrupt.queue_head;
-
-		if ((instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {
+		uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf);
+		uintptr_t real_pa = addr_to_phys(QH(interrupt));
+		if (expected_pa != real_pa) {
 			usb_log_debug("Interrupt QH: %p vs. %p.\n",
-				instance->frame_list[frnum] & (~0xf), addr_to_phys(qh));
-		}
-
-		if ((qh->next_queue & (~0xf))
-		  != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) {
-			usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf),
-				addr_to_phys(instance->transfers_control_slow.queue_head));
-		}
-		qh = instance->transfers_control_slow.queue_head;
-
-		if ((qh->next_queue & (~0xf))
-		  != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) {
-			usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf),
-				addr_to_phys(instance->transfers_control_full.queue_head));\
-		}
-		qh = instance->transfers_control_full.queue_head;
-
-		if ((qh->next_queue & (~0xf))
-		  != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) {
-			usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf),
-				addr_to_phys(instance->transfers_bulk_full.queue_head));
-		}
-/*
-	uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
-	cmd |= UHCI_CMD_RUN_STOP;
-	pio_write_16(&instance->registers->usbcmd, cmd);
-*/
+			    expected_pa, real_pa);
+		}
+
+		expected_pa = QH(interrupt)->next_queue & (~0xf);
+		real_pa = addr_to_phys(QH(control_slow));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Control Slow QH: %p vs. %p.\n",
+			    expected_pa, real_pa);
+		}
+
+		expected_pa = QH(control_slow)->next_queue & (~0xf);
+		real_pa = addr_to_phys(QH(control_full));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Control Full QH: %p vs. %p.\n",
+			    expected_pa, real_pa);
+		}
+
+		expected_pa = QH(control_full)->next_queue & (~0xf);
+		real_pa = addr_to_phys(QH(bulk_full));
+		if (expected_pa != real_pa ) {
+			usb_log_debug("Bulk QH: %p vs. %p.\n",
+			    expected_pa, real_pa);
+		}
 		async_usleep(UHCI_DEBUGER_TIMEOUT);
 	}
-	return 0;
-}
-/*----------------------------------------------------------------------------*/
+	return EOK;
+#undef QH
+}
+/*----------------------------------------------------------------------------*/
+/** Checks transfer packets, for USB validity
+ *
+ * @param[in] low_speed Transfer speed.
+ * @param[in] transfer Transer type
+ * @param[in] size Maximum size of used packets
+ * @return EOK
+ */
 bool allowed_usb_packet(
-	bool low_speed, usb_transfer_type_t transfer, size_t size)
+    bool low_speed, usb_transfer_type_t transfer, size_t size)
 {
 	/* see USB specification chapter 5.5-5.8 for magic numbers used here */
-	switch(transfer) {
-		case USB_TRANSFER_ISOCHRONOUS:
-			return (!low_speed && size < 1024);
-		case USB_TRANSFER_INTERRUPT:
-			return size <= (low_speed ? 8 : 64);
-		case USB_TRANSFER_CONTROL: /* device specifies its own max size */
-			return (size <= (low_speed ? 8 : 64));
-		case USB_TRANSFER_BULK: /* device specifies its own max size */
-			return (!low_speed && size <= 64);
+	switch(transfer)
+	{
+	case USB_TRANSFER_ISOCHRONOUS:
+		return (!low_speed && size < 1024);
+	case USB_TRANSFER_INTERRUPT:
+		return size <= (low_speed ? 8 : 64);
+	case USB_TRANSFER_CONTROL: /* device specifies its own max size */
+		return (size <= (low_speed ? 8 : 64));
+	case USB_TRANSFER_BULK: /* device specifies its own max size */
+		return (!low_speed && size <= 64);
 	}
 	return false;
Index: uspace/drv/uhci-hcd/uhci.h
===================================================================
--- uspace/drv/uhci-hcd/uhci.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/uhci.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -84,5 +84,5 @@
 	device_keeper_t device_manager;
 
-	volatile regs_t *registers;
+	regs_t *registers;
 
 	link_pointer_t *frame_list;
Index: uspace/drv/uhci-hcd/uhci_struct/queue_head.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/uhci_struct/queue_head.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -71,5 +71,5 @@
 }
 
-static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa)
+static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa)
 {
 	if (pa) {
@@ -78,15 +78,4 @@
 }
 
-static inline queue_head_t * queue_head_get() {
-	queue_head_t *ret = malloc32(sizeof(queue_head_t));
-	if (ret)
-		queue_head_init(ret);
-	return ret;
-}
-
-static inline void queue_head_dispose(queue_head_t *head)
-	{ free32(head); }
-
-
 #endif
 /**
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -38,9 +38,26 @@
 #include "utils/malloc32.h"
 
-void transfer_descriptor_init(transfer_descriptor_t *instance,
-    int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
-    usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next)
+/** Initializes Transfer Descriptor
+ *
+ * @param[in] instance Memory place to initialize.
+ * @param[in] err_count Number of retries hc should attempt.
+ * @param[in] size Size of data source.
+ * @param[in] toggle Value of toggle bit.
+ * @param[in] iso True if TD is for Isochronous transfer.
+ * @param[in] low_speed Target device's speed.
+ * @param[in] target Address and endpoint receiving the transfer.
+ * @param[in] pid Packet identification (SETUP, IN or OUT).
+ * @param[in] buffer Source of data.
+ * @param[in] next Net TD in transaction.
+ * @return Error code.
+ */
+void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
+    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
+    td_t *next)
 {
 	assert(instance);
+	assert(size < 1024);
+	assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
+	    || (pid == USB_PID_OUT));
 
 	instance->next = 0
@@ -49,15 +66,19 @@
 
 	instance->status = 0
-	  | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
-		| (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
-	  | TD_STATUS_ERROR_ACTIVE;
+	    | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
+	    | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
+	    | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
+	    | TD_STATUS_ERROR_ACTIVE;
 
-	assert(size < 1024);
+	if (pid == USB_PID_IN && !iso) {
+		instance->status |= TD_STATUS_SPD_FLAG;
+	}
+
 	instance->device = 0
-		| (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
-		| (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
-		| ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
-		| ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
-		| ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
+	    | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
+	    | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
+	    | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
+	    | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
+	    | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
 
 	instance->buffer_ptr = 0;
@@ -68,9 +89,18 @@
 
 	usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n",
-		instance->next, instance->status, instance->device,
-	  instance->buffer_ptr, buffer);
+	    instance->next, instance->status, instance->device,
+	    instance->buffer_ptr, buffer);
+	if (pid == USB_PID_SETUP) {
+		usb_log_debug("SETUP BUFFER: %s\n",
+			usb_debug_str_buffer(buffer, 8, 8));
+	}
 }
 /*----------------------------------------------------------------------------*/
-int transfer_descriptor_status(transfer_descriptor_t *instance)
+/** Converts TD status into standard error code
+ *
+ * @param[in] instance TD structure to use.
+ * @return Error code.
+ */
+int td_status(td_t *instance)
 {
 	assert(instance);
Index: uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -88,23 +88,39 @@
 	 * we don't use it anyway
 	 */
-} __attribute__((packed)) transfer_descriptor_t;
+} __attribute__((packed)) td_t;
 
 
-void transfer_descriptor_init(transfer_descriptor_t *instance,
-    int error_count, size_t size, bool toggle, bool isochronous, bool low_speed,
-    usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next);
+void td_init(td_t *instance, int error_count, size_t size, bool toggle, bool iso,
+    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
+    td_t *next);
 
-int transfer_descriptor_status(transfer_descriptor_t *instance);
+int td_status(td_t *instance);
 
-static inline size_t transfer_descriptor_actual_size(
-    transfer_descriptor_t *instance)
+static inline size_t td_act_size(td_t *instance)
 {
 	assert(instance);
 	return
-	    ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
+	    ((instance->status >> TD_STATUS_ACTLEN_POS) + 1)
+	    & TD_STATUS_ACTLEN_MASK;
 }
 
-static inline bool transfer_descriptor_is_active(
-    transfer_descriptor_t *instance)
+static inline bool td_is_short(td_t *instance)
+{
+	const size_t act_size = td_act_size(instance);
+	const size_t max_size =
+	    ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1)
+	    & TD_DEVICE_MAXLEN_MASK;
+	return
+	    (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
+}
+
+static inline int td_toggle(td_t *instance)
+{
+	assert(instance);
+	return ((instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) != 0)
+	    ? 1 : 0;
+}
+
+static inline bool td_is_active(td_t *instance)
 {
 	assert(instance);
Index: uspace/drv/uhci-hcd/utils/device_keeper.c
===================================================================
--- uspace/drv/uhci-hcd/utils/device_keeper.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/utils/device_keeper.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -39,4 +39,8 @@
 
 /*----------------------------------------------------------------------------*/
+/** Initializes device keeper structure.
+ *
+ * @param[in] instance Memory place to initialize.
+ */
 void device_keeper_init(device_keeper_t *instance)
 {
@@ -49,9 +53,14 @@
 		instance->devices[i].occupied = false;
 		instance->devices[i].handle = 0;
-	}
-}
-/*----------------------------------------------------------------------------*/
-void device_keeper_reserve_default(
-    device_keeper_t *instance, usb_speed_t speed)
+		instance->devices[i].toggle_status = 0;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Attempts to obtain address 0, blocks.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] speed Speed of the device requesting default address.
+ */
+void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed)
 {
 	assert(instance);
@@ -66,4 +75,9 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Attempts to obtain address 0, blocks.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] speed Speed of the device requesting default address.
+ */
 void device_keeper_release_default(device_keeper_t *instance)
 {
@@ -75,4 +89,100 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Checks setup data for signs of toggle reset.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device to receive setup packet.
+ * @param[in] data Setup packet data.
+ */
+void device_keeper_reset_if_need(
+    device_keeper_t *instance, usb_target_t target, const unsigned char *data)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		fibril_mutex_unlock(&instance->guard);
+		return;
+	}
+
+	switch (data[1])
+	{
+	case 0x01: /*clear feature*/
+		/* recipient is endpoint, value is zero (ENDPOINT_STALL) */
+		if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
+			/* endpoint number is < 16, thus first byte is enough */
+			instance->devices[target.address].toggle_status &=
+			    ~(1 << data[4]);
+		}
+	break;
+
+	case 0x9: /* set configuration */
+	case 0x11: /* set interface */
+		instance->devices[target.address].toggle_status = 0;
+	break;
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Gets current value of endpoint toggle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device and endpoint used.
+ * @return Error code
+ */
+int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
+{
+	assert(instance);
+	int ret;
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		ret = EINVAL;
+	} else {
+		ret =
+		    (instance->devices[target.address].toggle_status
+		        >> target.endpoint) & 1;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Sets current value of endpoint toggle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device and endpoint used.
+ * @param[in] toggle Current toggle value.
+ * @return Error code.
+ */
+int device_keeper_set_toggle(
+    device_keeper_t *instance, usb_target_t target, bool toggle)
+{
+	assert(instance);
+	int ret;
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		ret = EINVAL;
+	} else {
+		if (toggle) {
+			instance->devices[target.address].toggle_status |= (1 << target.endpoint);
+		} else {
+			instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
+		}
+		ret = EOK;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Gets a free USB address
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] speed Speed of the device requiring address.
+ * @return Free address, or error code.
+ */
 usb_address_t device_keeper_request(
     device_keeper_t *instance, usb_speed_t speed)
@@ -96,4 +206,5 @@
 	instance->devices[new_address].occupied = true;
 	instance->devices[new_address].speed = speed;
+	instance->devices[new_address].toggle_status = 0;
 	instance->last_address = new_address;
 	fibril_mutex_unlock(&instance->guard);
@@ -101,4 +212,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Binds USB address to devman handle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Device address
+ * @param[in] handle Devman handle of the device.
+ */
 void device_keeper_bind(
     device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
@@ -113,4 +230,9 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Releases used USB address.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Device address
+ */
 void device_keeper_release(device_keeper_t *instance, usb_address_t address)
 {
@@ -125,4 +247,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Finds USB address associated with the device
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] handle Devman handle of the device seeking its address.
+ * @return USB Address, or error code.
+ */
 usb_address_t device_keeper_find(
     device_keeper_t *instance, devman_handle_t handle)
@@ -142,4 +270,10 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Gets speed associated with the address
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Address of the device.
+ * @return USB speed.
+ */
 usb_speed_t device_keeper_speed(
     device_keeper_t *instance, usb_address_t address)
Index: uspace/drv/uhci-hcd/utils/device_keeper.h
===================================================================
--- uspace/drv/uhci-hcd/utils/device_keeper.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/utils/device_keeper.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -44,4 +44,5 @@
 	usb_speed_t speed;
 	bool occupied;
+	uint16_t toggle_status;
 	devman_handle_t handle;
 };
@@ -55,13 +56,26 @@
 
 void device_keeper_init(device_keeper_t *instance);
+
 void device_keeper_reserve_default(
     device_keeper_t *instance, usb_speed_t speed);
+
 void device_keeper_release_default(device_keeper_t *instance);
+
+void device_keeper_reset_if_need(
+    device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);
+
+int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);
+
+int device_keeper_set_toggle(
+    device_keeper_t *instance, usb_target_t target, bool toggle);
 
 usb_address_t device_keeper_request(
     device_keeper_t *instance, usb_speed_t speed);
+
 void device_keeper_bind(
     device_keeper_t *instance, usb_address_t address, devman_handle_t handle);
+
 void device_keeper_release(device_keeper_t *instance, usb_address_t address);
+
 usb_address_t device_keeper_find(
     device_keeper_t *instance, devman_handle_t handle);
Index: uspace/drv/uhci-hcd/utils/malloc32.h
===================================================================
--- uspace/drv/uhci-hcd/utils/malloc32.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-hcd/utils/malloc32.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -34,6 +34,4 @@
 #ifndef DRV_UHCI_TRANSLATOR_H
 #define DRV_UHCI_TRANSLATOR_H
-
-#include <usb/usbmem.h>
 
 #include <assert.h>
Index: uspace/drv/uhci-rhd/main.c
===================================================================
--- uspace/drv/uhci-rhd/main.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-rhd/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -35,10 +35,10 @@
 #include <devman.h>
 #include <device/hw_res.h>
+#include <errno.h>
 #include <usb_iface.h>
 #include <usb/ddfiface.h>
+#include <usb/debug.h>
 
-#include <errno.h>
 
-#include <usb/debug.h>
 
 #include "root_hub.h"
@@ -47,5 +47,5 @@
 static int hc_get_my_registers(ddf_dev_t *dev,
     uintptr_t *io_reg_address, size_t *io_reg_size);
-
+/*----------------------------------------------------------------------------*/
 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
 {
@@ -58,14 +58,19 @@
 	return EOK;
 }
-
+/*----------------------------------------------------------------------------*/
 static usb_iface_t uhci_rh_usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle,
 	.get_address = usb_iface_get_address_hub_impl
 };
-
+/*----------------------------------------------------------------------------*/
 static ddf_dev_ops_t uhci_rh_ops = {
 	.interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
 };
-
+/*----------------------------------------------------------------------------*/
+/** Initializes a new ddf driver instance of UHCI root hub.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
 static int uhci_rh_add_device(ddf_dev_t *device)
 {
@@ -104,9 +109,9 @@
 	return EOK;
 }
-
+/*----------------------------------------------------------------------------*/
 static driver_ops_t uhci_rh_driver_ops = {
 	.add_device = uhci_rh_add_device,
 };
-
+/*----------------------------------------------------------------------------*/
 static driver_t uhci_rh_driver = {
 	.name = NAME,
@@ -114,4 +119,12 @@
 };
 /*----------------------------------------------------------------------------*/
+/** Initializes global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
 int main(int argc, char *argv[])
 {
@@ -120,6 +133,13 @@
 }
 /*----------------------------------------------------------------------------*/
-int hc_get_my_registers(ddf_dev_t *dev,
-    uintptr_t *io_reg_address, size_t *io_reg_size)
+/** Get address of I/O registers.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the memory range.
+ * @param[out] io_reg_size Size of the memory range.
+ * @return Error code.
+ */
+int hc_get_my_registers(
+    ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
 {
 	assert(dev != NULL);
@@ -146,13 +166,13 @@
 	for (i = 0; i < hw_resources.count; i++) {
 		hw_resource_t *res = &hw_resources.resources[i];
-		switch (res->type) {
-			case IO_RANGE:
-				io_address = (uintptr_t)
-				    res->res.io_range.address;
-				io_size = res->res.io_range.size;
-				io_found = true;
-				break;
-			default:
-				break;
+		switch (res->type)
+		{
+		case IO_RANGE:
+			io_address = (uintptr_t) res->res.io_range.address;
+			io_size = res->res.io_range.size;
+			io_found = true;
+
+		default:
+			break;
 		}
 	}
@@ -170,7 +190,7 @@
 	}
 	rc = EOK;
+
 leave:
 	async_hangup(parent_phone);
-
 	return rc;
 }
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-rhd/port.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -46,15 +46,26 @@
 #include "port_status.h"
 
-static int uhci_port_new_device(uhci_port_t *port, uint16_t status);
+static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
 static int uhci_port_remove_device(uhci_port_t *port);
 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
 static int uhci_port_check(void *port);
-static int new_device_enable_port(int portno, void *arg);
-
-int uhci_port_init(
-  uhci_port_t *port, port_status_t *address, unsigned number,
-  unsigned usec, ddf_dev_t *rh)
+static int uhci_port_reset_enable(int portno, void *arg);
+/*----------------------------------------------------------------------------*/
+/** Initializes UHCI root hub port instance.
+ *
+ * @param[in] port Memory structure to use.
+ * @param[in] addr Address of I/O register.
+ * @param[in] number Port number.
+ * @param[in] usec Polling interval.
+ * @param[in] rh Pointer to ddf instance fo the root hub driver.
+ * @return Error code.
+ *
+ * Starts the polling fibril.
+ */
+int uhci_port_init(uhci_port_t *port,
+    port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh)
 {
 	assert(port);
+
 	port->address = address;
 	port->number = number;
@@ -62,4 +73,5 @@
 	port->attached_device = 0;
 	port->rh = rh;
+
 	int rc = usb_hc_connection_initialize_from_device(
 	    &port->hc_connection, rh);
@@ -75,4 +87,5 @@
 		return ENOMEM;
 	}
+
 	fibril_add_ready(port->checker);
 	usb_log_debug("Port(%p - %d): Added fibril. %x\n",
@@ -81,76 +94,87 @@
 }
 /*----------------------------------------------------------------------------*/
+/** Finishes UHCI root hub port instance.
+ *
+ * @param[in] port Memory structure to use.
+ *
+ * Stops the polling fibril.
+ */
 void uhci_port_fini(uhci_port_t *port)
 {
-// TODO: destroy fibril
-// TODO: hangup phone
-//	fibril_teardown(port->checker);
+	/* TODO: Kill fibril here */
 	return;
 }
 /*----------------------------------------------------------------------------*/
+/** Periodically checks port status and reports new devices.
+ *
+ * @param[in] port Memory structure to use.
+ * @return Error code.
+ */
 int uhci_port_check(void *port)
 {
-	uhci_port_t *port_instance = port;
-	assert(port_instance);
-//	port_status_write(port_instance->address, 0);
-
+	uhci_port_t *instance = port;
+	assert(instance);
+
+	/* Iteration count, for debug purposes only */
 	unsigned count = 0;
 
 	while (1) {
-		async_usleep(port_instance->wait_period_usec);
+		async_usleep(instance->wait_period_usec);
 
 		/* read register value */
-		port_status_t port_status =
-			port_status_read(port_instance->address);
-
-		/* debug print */
-		static fibril_mutex_t dbg_mtx = FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
+		port_status_t port_status = port_status_read(instance->address);
+
+		/* debug print mutex */
+		static fibril_mutex_t dbg_mtx =
+		    FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
 		fibril_mutex_lock(&dbg_mtx);
 		usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n",
-		  port_instance->address, port_instance->number, port_status, count++);
+		  instance->address, instance->number, port_status, count++);
 //		print_port_status(port_status);
 		fibril_mutex_unlock(&dbg_mtx);
 
-		if ((port_status & STATUS_CONNECTED_CHANGED) != 0) {
-			usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
-			    port_instance->address, port_instance->number, port_status);
-
-
-			int rc = usb_hc_connection_open(
-			    &port_instance->hc_connection);
-			if (rc != EOK) {
-				usb_log_error("Port(%p - %d): Failed to connect to HC.",
-				    port_instance->address, port_instance->number);
-				continue;
-			}
-
-			/* remove any old device */
-			if (port_instance->attached_device) {
-				usb_log_debug("Port(%p - %d): Removing device.\n",
-				    port_instance->address, port_instance->number);
-				uhci_port_remove_device(port_instance);
-			}
-
-			if ((port_status & STATUS_CONNECTED) != 0) {
-				/* new device */
-				uhci_port_new_device(port_instance, port_status);
-			} else {
-				/* ack changes by writing one to WC bits */
-				port_status_write(port_instance->address, port_status);
-				usb_log_debug("Port(%p - %d): Change status ACK.\n",
-						port_instance->address, port_instance->number);
-			}
-
-			rc = usb_hc_connection_close(
-			    &port_instance->hc_connection);
-			if (rc != EOK) {
-				usb_log_error("Port(%p - %d): Failed to disconnect from HC.",
-				    port_instance->address, port_instance->number);
-			}
-		}
-	}
-	return EOK;
-}
-
+		if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
+			continue;
+
+		usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
+		    instance->address, instance->number, port_status);
+
+		int rc =
+		    usb_hc_connection_open(&instance->hc_connection);
+		if (rc != EOK) {
+			usb_log_error("Port(%p - %d): Failed to connect to HC.",
+			    instance->address, instance->number);
+			continue;
+		}
+
+		/* Remove any old device */
+		if (instance->attached_device) {
+			usb_log_debug2("Port(%p - %d): Removing device.\n",
+			    instance->address, instance->number);
+			uhci_port_remove_device(instance);
+		}
+
+		if ((port_status & STATUS_CONNECTED) != 0) {
+			/* New device */
+			const usb_speed_t speed =
+			    ((port_status & STATUS_LOW_SPEED) != 0) ?
+			    USB_SPEED_LOW : USB_SPEED_FULL;
+			uhci_port_new_device(instance, speed);
+		} else {
+			/* Write one to WC bits, to ack changes */
+			port_status_write(instance->address, port_status);
+			usb_log_debug("Port(%p - %d): Change status ACK.\n",
+			    instance->address, instance->number);
+		}
+
+		rc = usb_hc_connection_close(&instance->hc_connection);
+		if (rc != EOK) {
+			usb_log_error("Port(%p - %d): Failed to disconnect.",
+			    instance->address, instance->number);
+		}
+	}
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
 /** Callback for enabling port during adding a new device.
  *
@@ -159,5 +183,5 @@
  * @return Error code.
  */
-static int new_device_enable_port(int portno, void *arg)
+int uhci_port_reset_enable(int portno, void *arg)
 {
 	uhci_port_t *port = (uhci_port_t *) arg;
@@ -184,6 +208,5 @@
 		port_status_write(port->address, port_status);
 		async_usleep(10000);
-		port_status =
-			port_status_read(port->address);
+		port_status = port_status_read(port->address);
 		port_status &= ~STATUS_IN_RESET;
 		port_status_write(port->address, port_status);
@@ -194,10 +217,16 @@
 	/* Enable the port. */
 	uhci_port_set_enabled(port, true);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-static int uhci_port_new_device(uhci_port_t *port, uint16_t status)
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initializes and reports connected device.
+ *
+ * @param[in] port Memory structure to use.
+ * @param[in] speed Detected speed.
+ * @return Error code.
+ *
+ * Uses libUSB function to do the actual work.
+ */
+int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed)
 {
 	assert(port);
@@ -209,10 +238,9 @@
 	usb_address_t dev_addr;
 	int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
-	    ((status & STATUS_LOW_SPEED) != 0) ? USB_SPEED_LOW : USB_SPEED_FULL,
-	    new_device_enable_port, port->number, port,
+	    speed, uhci_port_reset_enable, port->number, port,
 	    &dev_addr, &port->attached_device, NULL, NULL, NULL);
 
 	if (rc != EOK) {
-		usb_log_error("Port(%p-%d): Failed(%d) adding new device: %s.\n",
+		usb_log_error("Port(%p-%d): Failed(%d) to add device: %s.\n",
 		    port->address, port->number, rc, str_error(rc));
 		uhci_port_set_enabled(port, false);
@@ -225,23 +253,32 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-static int uhci_port_remove_device(uhci_port_t *port)
+/*----------------------------------------------------------------------------*/
+/** Removes device.
+ *
+ * @param[in] port Memory structure to use.
+ * @return Error code.
+ *
+ * Does not work DDF does not support device removal.
+ */
+int uhci_port_remove_device(uhci_port_t *port)
 {
 	usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n",
-		port->address, port->number, (unsigned int)port->attached_device);
-//	uhci_port_set_enabled(port, false);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
+	    port->address, port->number, (unsigned int)port->attached_device);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Enables and disables port.
+ *
+ * @param[in] port Memory structure to use.
+ * @return Error code. (Always EOK)
+ */
+int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
 {
 	assert(port);
 
-	/* read register value */
-	port_status_t port_status
-		= port_status_read(port->address);
-
-	/* enable port: register write */
+	/* Read register value */
+	port_status_t port_status = port_status_read(port->address);
+
+	/* Set enabled bit */
 	if (enabled) {
 		port_status |= STATUS_ENABLED;
@@ -249,4 +286,6 @@
 		port_status &= ~STATUS_ENABLED;
 	}
+
+	/* Write new value. */
 	port_status_write(port->address, port_status);
 
Index: uspace/drv/uhci-rhd/port_status.c
===================================================================
--- uspace/drv/uhci-rhd/port_status.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-rhd/port_status.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -60,4 +60,9 @@
 };
 
+/** Prints portr status in a human readable way.
+ *
+ * @param[in] value Port value to print.
+ * @return Error code.
+ */
 void print_port_status(port_status_t value)
 {
Index: uspace/drv/uhci-rhd/root_hub.c
===================================================================
--- uspace/drv/uhci-rhd/root_hub.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/uhci-rhd/root_hub.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -40,4 +40,12 @@
 #include "root_hub.h"
 
+/** Initializes UHCI root hub instance.
+ *
+ * @param[in] instance Driver memory structure to use.
+ * @param[in] addr Address of I/O registers.
+ * @param[in] size Size of available I/O space.
+ * @param[in] rh Pointer to ddf instance fo the root hub driver.
+ * @return Error code.
+ */
 int uhci_root_hub_init(
   uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
@@ -47,11 +55,11 @@
 	int ret;
 
-	/* allow access to root hub registers */
-	assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size);
+	/* Allow access to root hub port registers */
+	assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);
 	port_status_t *regs;
 	ret = pio_enable(addr, size, (void**)&regs);
-
 	if (ret < 0) {
-		usb_log_error("Failed to gain access to port registers at %p\n", regs);
+		usb_log_error(
+		    "Failed to gain access to port registers at %p\n", regs);
 		return ret;
 	}
@@ -60,7 +68,7 @@
 	unsigned i = 0;
 	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
-		/* mind pointer arithmetics */
+		/* NOTE: mind pointer arithmetics here */
 		ret = uhci_port_init(
-		  &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
+		    &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
 		if (ret != EOK) {
 			unsigned j = 0;
@@ -74,10 +82,16 @@
 }
 /*----------------------------------------------------------------------------*/
-int uhci_root_hub_fini( uhci_root_hub_t* instance )
+/** Finishes UHCI root hub instance.
+ *
+ * @param[in] instance Driver memory structure to use.
+ * @return Error code.
+ */
+int uhci_root_hub_fini(uhci_root_hub_t* instance)
 {
-	assert( instance );
-	// TODO:
-	//destroy fibril here
-	//disable access to registers
+	assert(instance);
+	unsigned i = 0;
+	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
+		uhci_port_fini(&instance->ports[i]);
+	}
 	return EOK;
 }
Index: uspace/drv/usbhid/hiddev.c
===================================================================
--- uspace/drv/usbhid/hiddev.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhid/hiddev.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -135,4 +135,6 @@
 	}
 	
+	hid_dev->report_desc_size = length;
+	
 	usb_log_debug("Done.\n");
 	
@@ -149,41 +151,14 @@
 	usb_log_info("Processing descriptors...\n");
 	
-	// get the first configuration descriptor
-	usb_standard_configuration_descriptor_t config_desc;
-	
 	int rc;
-	rc = usb_request_get_bare_configuration_descriptor(&hid_dev->ctrl_pipe,
-	    0, &config_desc);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to get bare config descriptor: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	// prepare space for all underlying descriptors
-	uint8_t *descriptors = (uint8_t *)malloc(config_desc.total_length);
-	if (descriptors == NULL) {
-		usb_log_error("No memory!.\n");
-		return ENOMEM;
-	}
-	
-	size_t transferred = 0;
-	// get full configuration descriptor
-	rc = usb_request_get_full_configuration_descriptor(&hid_dev->ctrl_pipe,
-	    0, descriptors, config_desc.total_length, &transferred);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to get full config descriptor: %s.\n",
-		    str_error(rc));
-		free(descriptors);
-		return rc;
-	}
-	
-	if (transferred != config_desc.total_length) {
-		usb_log_error("Configuration descriptor has wrong size (%u, "
-		    "expected %u).\n", transferred, config_desc.total_length);
-		free(descriptors);
-		return ELIMIT;
+
+	uint8_t *descriptors = NULL;
+	size_t descriptors_size;
+	rc = usb_request_get_full_configuration_descriptor_alloc(
+	    &hid_dev->ctrl_pipe, 0, (void **) &descriptors, &descriptors_size);
+	if (rc != EOK) {
+		usb_log_error("Failed to retrieve config descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
 	}
 	
@@ -201,5 +176,5 @@
 	
 	rc = usb_endpoint_pipe_initialize_from_configuration(
-	    endpoint_mapping, 1, descriptors, config_desc.total_length,
+	    endpoint_mapping, 1, descriptors, descriptors_size,
 	    &hid_dev->wire);
 	
@@ -233,5 +208,12 @@
 	assert(endpoint_mapping[0].interface != NULL);
 	
-	rc = usbhid_dev_get_report_descriptor(hid_dev, descriptors, transferred,
+	/*
+	 * Save polling interval
+	 */
+	hid_dev->poll_interval = endpoint_mapping[0].descriptor->poll_interval;
+	assert(hid_dev->poll_interval > 0);
+	
+	rc = usbhid_dev_get_report_descriptor(hid_dev,
+	    descriptors, descriptors_size,
 	    (uint8_t *)endpoint_mapping[0].interface);
 	
@@ -239,8 +221,18 @@
 	
 	if (rc != EOK) {
-		usb_log_warning("Problem with parsing Report descriptor: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
+		usb_log_warning("Problem with getting Report descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	rc = usb_hid_parse_report_descriptor(hid_dev->parser, 
+	    hid_dev->report_desc, hid_dev->report_desc_size);
+	if (rc != EOK) {
+		usb_log_warning("Problem parsing Report descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_hid_descriptor_print(hid_dev->parser);
 	
 	return EOK;
@@ -263,4 +255,12 @@
 	memset(dev, 0, sizeof(usbhid_dev_t));
 	
+	dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
+	    usb_hid_report_parser_t)));
+	if (dev->parser == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(dev);
+		return NULL;
+	}
+	
 	dev->initialized = 0;
 	
@@ -339,4 +339,13 @@
 		return rc;
 	}
+	
+	/*
+	 * Initialize the report parser.
+	 */
+	rc = usb_hid_parser_init(hid_dev->parser);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize report parser.\n");
+		return rc;
+	}
 
 	/*
Index: uspace/drv/usbhid/hiddev.h
===================================================================
--- uspace/drv/usbhid/hiddev.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhid/hiddev.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -57,7 +57,10 @@
 	usb_endpoint_pipe_t poll_pipe;
 	
+	short poll_interval;
+	
 	uint16_t iface;
 	
 	uint8_t *report_desc;
+	size_t report_desc_size;
 	usb_hid_report_parser_t *parser;
 	
Index: uspace/drv/usbhid/hidreq.c
===================================================================
--- uspace/drv/usbhid/hidreq.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhid/hidreq.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -69,4 +69,7 @@
 		return sess_rc;
 	}
+	
+	uint16_t value = 0;
+	value |= (type << 8);
 
 	usb_log_debug("Sending Set_Report request to the device.\n");
@@ -74,5 +77,5 @@
 	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
 	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_SET_REPORT, type, hid_dev->iface, buffer, buf_size);
+	    USB_HIDREQ_SET_REPORT, value, hid_dev->iface, buffer, buf_size);
 
 	sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
@@ -137,4 +140,222 @@
 		return sess_rc;
 	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration)
+{
+	if (hid_dev == NULL) {
+		usb_log_error("usbhid_req_set_idle(): no HID device "
+		    "structure given.\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Set_Idle request to the device ("
+	    "duration: %u, iface: %d).\n", duration, hid_dev->iface);
+	
+	uint16_t value = duration << 8;
+	
+	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_IDLE, value, hid_dev->iface, NULL, 0);
+
+	sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type, 
+    uint8_t *buffer, size_t buf_size, size_t *actual_size)
+{
+	if (hid_dev == NULL) {
+		usb_log_error("usbhid_req_set_report(): no HID device structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	uint16_t value = 0;
+	value |= (type << 8);
+	
+	usb_log_debug("Sending Get_Report request to the device.\n");
+	
+	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_REPORT, value, hid_dev->iface, buffer, buf_size,
+	    actual_size);
+
+	sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	return EOK;
+}
+
+int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol)
+{
+	if (hid_dev == NULL) {
+		usb_log_error("usbhid_req_set_protocol(): no HID device "
+		    "structure given.\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Get_Protocol request to the device ("
+	    "iface: %d).\n", hid_dev->iface);
+	
+	uint8_t buffer[1];
+	size_t actual_size = 0;
+	
+	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_PROTOCOL, 0, hid_dev->iface, buffer, 1, &actual_size);
+
+	sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	if (actual_size != 1) {
+		usb_log_warning("Wrong data size: %zu, expected: 1.\n",
+			actual_size);
+		return ELIMIT;
+	}
+	
+	*protocol = buffer[0];
+	
+	return EOK;
+}
+
+int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration)
+{
+	if (hid_dev == NULL) {
+		usb_log_error("usbhid_req_set_idle(): no HID device "
+		    "structure given.\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Get_Idle request to the device ("
+	    "iface: %d).\n", hid_dev->iface);
+	
+	uint16_t value = 0;
+	uint8_t buffer[1];
+	size_t actual_size = 0;
+	
+	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_IDLE, value, hid_dev->iface, buffer, 1, 
+	    &actual_size);
+
+	sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	if (actual_size != 1) {
+		usb_log_warning("Wrong data size: %zu, expected: 1.\n",
+			actual_size);
+		return ELIMIT;
+	}
+	
+	*duration = buffer[0];
 	
 	return EOK;
Index: uspace/drv/usbhid/hidreq.h
===================================================================
--- uspace/drv/usbhid/hidreq.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhid/hidreq.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -50,4 +50,13 @@
 int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol);
 
+int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration);
+
+int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type, 
+    uint8_t *buffer, size_t buf_size, size_t *actual_size);
+
+int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol);
+
+int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration);
+
 /*----------------------------------------------------------------------------*/
 
Index: uspace/drv/usbhid/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbddev.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhid/kbddev.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -38,4 +38,5 @@
 #include <str_error.h>
 #include <fibril.h>
+#include <stdio.h>
 
 #include <io/keycode.h>
@@ -62,4 +63,6 @@
 static const size_t BOOTP_BUFFER_SIZE = 8;
 static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
+static const uint8_t BOOTP_ERROR_ROLLOVER = 1;
+static const uint8_t IDLE_RATE = 0;
 
 /** Keyboard polling endpoint description for boot protocol class. */
@@ -149,5 +152,4 @@
 	uint8_t buffer[BOOTP_BUFFER_OUT_SIZE];
 	int rc= 0;
-	unsigned i;
 	
 	memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE);
@@ -177,19 +179,11 @@
 	}
 	
-	// TODO: REFACTOR!!!
-	
-	usb_log_debug("Output report buffer: ");
-	for (i = 0; i < BOOTP_BUFFER_OUT_SIZE; ++i) {
-		usb_log_debug("0x%x ", buffer[i]);
-	}
-	usb_log_debug("\n");
-	
-	uint16_t value = 0;
-	value |= (USB_HID_REPORT_TYPE_OUTPUT << 8);
-
+	usb_log_debug("Output report buffer: %s\n", 
+	    usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0));
+	
 	assert(kbd_dev->hid_dev != NULL);
 	assert(kbd_dev->hid_dev->initialized);
-	usbhid_req_set_report(kbd_dev->hid_dev, value, buffer, 
-	    BOOTP_BUFFER_OUT_SIZE);
+	usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 
+	    buffer, BOOTP_BUFFER_OUT_SIZE);
 }
 
@@ -228,11 +222,5 @@
 
 	if (mod_mask != 0) {
-		usb_log_debug2("\n\nChanging mods and lock keys\n");
-		usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods);
-		usb_log_debug2("\nLock keys before:0x%x\n\n", 
-		    kbd_dev->lock_keys);
-		
 		if (type == KEY_PRESS) {
-			usb_log_debug2("\nKey pressed.\n");
 			/*
 			 * Only change lock state on transition from released
@@ -247,12 +235,8 @@
  			usbhid_kbd_set_led(kbd_dev);
 		} else {
-			usb_log_debug2("\nKey released.\n");
 			kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
 		}
 	}
 
-	usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods);
-	usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys);
-	
 	if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) {
 		// do not send anything to the console, this is our business
@@ -281,13 +265,13 @@
 	ev.key = key;
 	ev.mods = kbd_dev->mods;
-	
-	if (ev.mods & KM_NUM_LOCK) {
-		usb_log_debug("\n\nNum Lock turned on.\n\n");
-	}
 
 	ev.c = layout[active_layout]->parse_ev(&ev);
 
 	usb_log_debug2("Sending key %d to the console\n", ev.key);
-	assert(kbd_dev->console_phone != -1);
+	if (kbd_dev->console_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
 	
 	async_msg_4(kbd_dev->console_phone, KBD_EVENT, ev.type, ev.key, 
@@ -336,8 +320,21 @@
     const uint8_t *key_codes)
 {
-	// TODO: phantom state!!
-	
 	unsigned int key;
 	unsigned int i, j;
+	
+	/*
+	 * First of all, check if the kbd have reported phantom state.
+	 */
+	i = 0;
+	// all fields should report Error Rollover
+	while (i < kbd_dev->keycode_count &&
+	    key_codes[i] == BOOTP_ERROR_ROLLOVER) {
+		++i;
+	}
+	if (i == kbd_dev->keycode_count) {
+		usb_log_debug("Phantom state occured.\n");
+		// phantom state, do nothing
+		return;
+	}
 	
 	// TODO: quite dummy right now, think of better implementation
@@ -358,5 +355,5 @@
 			key = usbhid_parse_scancode(kbd_dev->keycodes[j]);
 			usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
-			usb_log_debug2("\nKey released: %d\n", key);
+			usb_log_debug2("Key released: %d\n", key);
 		} else {
 			// found, nothing happens
@@ -378,5 +375,5 @@
 			// not found, i.e. new key pressed
 			key = usbhid_parse_scancode(key_codes[i]);
-			usb_log_debug2("\nKey pressed: %d (keycode: %d)\n", key,
+			usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
 			    key_codes[i]);
 			usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
@@ -385,11 +382,18 @@
 		}
 	}
+//	// report all currently pressed keys
+//	for (i = 0; i < kbd_dev->keycode_count; ++i) {
+//		if (key_codes[i] != 0) {
+//			key = usbhid_parse_scancode(key_codes[i]);
+//			usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
+//			    key_codes[i]);
+//			usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
+//		}
+//	}
 	
 	memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count);
-	
-	usb_log_debug2("\nNew stored keycodes: ");
-	for (i = 0; i < kbd_dev->keycode_count; ++i) {
-		usb_log_debug2("%d ", kbd_dev->keycodes[i]);
-	}
+
+	usb_log_debug("New stored keycodes: %s\n", 
+	    usb_debug_str_buffer(kbd_dev->keycodes, kbd_dev->keycode_count, 0));
 }
 
@@ -406,14 +410,10 @@
 		return;
 	}
-
-	usb_log_debug2("Got keys from parser: ");
-	unsigned i;
-	for (i = 0; i < count; ++i) {
-		usb_log_debug2("%d ", key_codes[i]);
-	}
-	usb_log_debug2("\n");
 	
 	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
 	assert(kbd_dev != NULL);
+
+	usb_log_debug("Got keys from parser: %s\n", 
+	    usb_debug_str_buffer(key_codes, kbd_dev->keycode_count, 0));
 	
 	if (count != kbd_dev->keycode_count) {
@@ -440,12 +440,11 @@
 	callbacks->keyboard = usbhid_kbd_process_keycodes;
 
-	//usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 
-	//    NULL);
-	/*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size"
-	    " %zu\n", actual_size);*/
-	//dump_buffer("bufffer: ", buffer, actual_size);
-	
-	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
-	    callbacks, kbd_dev);
+	usb_log_debug("Calling usb_hid_parse_report() with "
+	    "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
+	
+//	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
+//	    callbacks, kbd_dev);
+	int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer,
+	    actual_size, callbacks, kbd_dev);
 	
 	if (rc != EOK) {
@@ -499,4 +498,6 @@
 	}
 	
+	usb_hid_free_report_parser((*kbd_dev)->parser);
+	
 	free(*kbd_dev);
 	*kbd_dev = NULL;
@@ -555,10 +556,13 @@
 	 * Set boot protocol.
 	 * Set LEDs according to initial setup.
+	 * Set Idle rate
 	 */
 	assert(kbd_dev->hid_dev != NULL);
 	assert(kbd_dev->hid_dev->initialized);
-	usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
+	//usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
 	
 	usbhid_kbd_set_led(kbd_dev);
+	
+	usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
 	
 	kbd_dev->initialized = 1;
@@ -589,6 +593,4 @@
 
 	while (true) {
-		async_usleep(1000 * 10);
-
 		sess_rc = usb_endpoint_pipe_start_session(
 		    &kbd_dev->hid_dev->poll_pipe);
@@ -631,4 +633,7 @@
 		usb_log_debug("Calling usbhid_kbd_process_data()\n");
 		usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
+		
+		// disabled for now, no reason to sleep
+		//async_usleep(kbd_dev->hid_dev->poll_interval);
 	}
 
Index: uspace/drv/usbhid/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbddev.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhid/kbddev.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -40,4 +40,5 @@
 
 #include <usb/classes/hid.h>
+#include <usb/classes/hidparser.h>
 #include <ddf/driver.h>
 #include <usb/pipes.h>
@@ -62,4 +63,6 @@
 	int console_phone;
 	
+	usb_hid_report_parser_t *parser;
+	
 	int initialized;
 } usbhid_kbd_t;
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhid/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -80,5 +80,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_INFO, NAME);
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
 	return ddf_driver_main(&kbd_driver);
 }
Index: uspace/drv/usbhid/usbhid.ma
===================================================================
--- uspace/drv/usbhid/usbhid.ma	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhid/usbhid.ma	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -1,4 +1,2 @@
-10 usb&class=hid
-10 usb&class=HID
+100 usb&interface&class=HID&subclass=0x01&protocol=0x01
 10 usb&interface&class=HID
-10 usb&hid
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbhub/usbhub.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -149,48 +149,29 @@
 	}
 
-	//configuration descriptor
-	/// \TODO check other configurations?
-	usb_standard_configuration_descriptor_t config_descriptor;
-	opResult = usb_request_get_bare_configuration_descriptor(
+	/* Retrieve full configuration descriptor. */
+	uint8_t *descriptors = NULL;
+	size_t descriptors_size = 0;
+	opResult = usb_request_get_full_configuration_descriptor_alloc(
 	    &hub->endpoints.control, 0,
-        &config_descriptor);
-	if(opResult!=EOK){
-		dprintf(USB_LOG_LEVEL_ERROR, "could not get configuration descriptor, %d",opResult);
+	    (void **) &descriptors, &descriptors_size);
+	if (opResult != EOK) {
+		usb_log_error("Could not get configuration descriptor: %s.\n",
+		    str_error(opResult));
 		return opResult;
 	}
-	//set configuration
+	usb_standard_configuration_descriptor_t *config_descriptor
+	    = (usb_standard_configuration_descriptor_t *) descriptors;
+
+	/* Set configuration. */
 	opResult = usb_request_set_configuration(&hub->endpoints.control,
-		config_descriptor.configuration_number);
-
-	if (opResult != EOK) {
-		dprintf(USB_LOG_LEVEL_ERROR,
-				"something went wrong when setting hub`s configuration, %d",
-				opResult);
+	    config_descriptor->configuration_number);
+
+	if (opResult != EOK) {
+		usb_log_error("Failed to set hub configuration: %s.\n",
+		    str_error(opResult));
 		return opResult;
 	}
 	dprintf(USB_LOG_LEVEL_DEBUG, "\tused configuration %d",
-			config_descriptor.configuration_number);
-
-	//full configuration descriptor
-	size_t transferred = 0;
-	uint8_t * descriptors = (uint8_t *)malloc(config_descriptor.total_length);
-	if (descriptors == NULL) {
-		dprintf(USB_LOG_LEVEL_ERROR, "insufficient memory");
-		return ENOMEM;
-	}
-	opResult = usb_request_get_full_configuration_descriptor(&hub->endpoints.control,
-	    0, descriptors,
-	    config_descriptor.total_length, &transferred);
-	if(opResult!=EOK){
-		free(descriptors);
-		dprintf(USB_LOG_LEVEL_ERROR,
-				"could not get full configuration descriptor, %d",opResult);
-		return opResult;
-	}
-	if (transferred != config_descriptor.total_length) {
-		dprintf(USB_LOG_LEVEL_ERROR,
-				"received incorrect full configuration descriptor");
-		return ELIMIT;
-	}
+			config_descriptor->configuration_number);
 
 	usb_endpoint_mapping_t endpoint_mapping[1] = {
@@ -204,5 +185,5 @@
 	opResult = usb_endpoint_pipe_initialize_from_configuration(
 	    endpoint_mapping, 1,
-	    descriptors, config_descriptor.total_length,
+	    descriptors, descriptors_size,
 	    &hub->device_connection);
 	if (opResult != EOK) {
@@ -252,4 +233,7 @@
 	dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction");
 	usb_endpoint_pipe_start_session(&result->endpoints.control);
+	opResult = usb_request_set_configuration(&result->endpoints.control, 1);
+	assert(opResult == EOK);
+
 	opResult = usb_request_get_descriptor(&result->endpoints.control,
 			USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
@@ -262,5 +246,6 @@
 		dprintf(USB_LOG_LEVEL_ERROR, "failed when receiving hub descriptor, badcode = %d",opResult);
 		free(serialized_descriptor);
-		return result;
+		free(result);
+		return NULL;
 	}
 	dprintf(USB_LOG_LEVEL_DEBUG2, "deserializing descriptor");
@@ -268,6 +253,6 @@
 	if(descriptor==NULL){
 		dprintf(USB_LOG_LEVEL_WARNING, "could not deserialize descriptor ");
-		result->port_count = 1;///\TODO this code is only for debug!!!
-		return result;
+		free(result);
+		return NULL;
 	}
 
@@ -305,4 +290,7 @@
 
 	usb_hub_info_t * hub_info = usb_create_hub_info(dev);
+	if(!hub_info){
+		return EINTR;
+	}
 
 	int opResult;
@@ -313,5 +301,5 @@
 	opResult = usb_hub_process_configuration_descriptors(hub_info);
 	if(opResult != EOK){
-		dprintf(USB_LOG_LEVEL_ERROR,"could not get condiguration descriptors, %d",
+		dprintf(USB_LOG_LEVEL_ERROR,"could not get configuration descriptors, %d",
 				opResult);
 		return opResult;
Index: uspace/drv/usbmid/explore.c
===================================================================
--- uspace/drv/usbmid/explore.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbmid/explore.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -42,56 +42,4 @@
 #include "usbmid.h"
 
-/** Allocate and retrieve full configuration descriptor.
- *
- * @param[in] dev USB device.
- * @param[in] config_index Configuration index.
- * @param[out] size Pointer where to store size of the allocated buffer.
- * @return Allocated full configuration descriptor.
- * @retval NULL Error occured.
- */
-static void *get_configuration_descriptor(usbmid_device_t *dev,
-    size_t config_index, size_t *size)
-{
-	usb_standard_configuration_descriptor_t config_descriptor;
-	int rc = usb_request_get_bare_configuration_descriptor(&dev->ctrl_pipe,
-	    config_index, &config_descriptor);
-	if (rc != EOK) {
-		usb_log_error("Failed getting configuration descriptor: %s.\n",
-		    str_error(rc));
-		return NULL;
-	}
-
-	void *full_config_descriptor = malloc(config_descriptor.total_length);
-	if (full_config_descriptor == NULL) {
-		usb_log_fatal("Out of memory (wanted: %zuB).\n",
-		    (size_t) config_descriptor.total_length);
-		return NULL;
-	}
-
-	size_t full_config_descriptor_size;
-	rc = usb_request_get_full_configuration_descriptor(&dev->ctrl_pipe,
-	    config_index,
-	    full_config_descriptor, config_descriptor.total_length,
-	    &full_config_descriptor_size);
-	if (rc != EOK) {
-		usb_log_error("Failed getting configuration descriptor: %s.\n",
-		    str_error(rc));
-		free(full_config_descriptor);
-		return NULL;
-	}
-
-	if (full_config_descriptor_size != config_descriptor.total_length) {
-		usb_log_error("Failed getting full configuration descriptor.\n");
-		free(full_config_descriptor);
-		return NULL;
-	}
-
-	if (size != NULL) {
-		*size = full_config_descriptor_size;
-	}
-
-	return full_config_descriptor;
-}
-
 /** Find starting indexes of all interface descriptors in a configuration.
  *
@@ -178,7 +126,11 @@
 
 	size_t config_descriptor_size;
-	uint8_t *config_descriptor_raw = get_configuration_descriptor(dev, 0,
-	    &config_descriptor_size);
-	if (config_descriptor_raw == NULL) {
+	uint8_t *config_descriptor_raw = NULL;
+	rc = usb_request_get_full_configuration_descriptor_alloc(
+	    &dev->ctrl_pipe, 0,
+	    (void **) &config_descriptor_raw, &config_descriptor_size);
+	if (rc != EOK) {
+		usb_log_error("Failed getting full config descriptor: %s.\n",
+		    str_error(rc));
 		return false;
 	}
@@ -207,4 +159,17 @@
 	}
 
+	/* Select the first configuration */
+	rc = usb_request_set_configuration(&dev->ctrl_pipe,
+	    config_descriptor->configuration_number);
+	if (rc != EOK) {
+		usb_log_error("Failed to set device configuration: %s.\n",
+		    str_error(rc));
+		free(config_descriptor_raw);
+		free(interface_descriptors);
+		return false;
+	}
+
+
+	/* Create control function */
 	ddf_fun_t *ctl_fun = ddf_fun_create(dev->dev, fun_exposed, "ctl");
 	if (ctl_fun == NULL) {
@@ -223,4 +188,5 @@
 	}
 
+	/* Spawn interface children */
 	size_t i;
 	for (i = 0; i < interface_descriptors_count; i++) {
Index: uspace/drv/usbmid/main.c
===================================================================
--- uspace/drv/usbmid/main.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbmid/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -44,4 +44,9 @@
 #include "usbmid.h"
 
+/** Callback when new MID device is attached to the host.
+ *
+ * @param gen_dev Generic DDF device representing the new device.
+ * @return Error code.
+ */
 static int usbmid_add_device(ddf_dev_t *gen_dev)
 {
@@ -86,8 +91,10 @@
 }
 
+/** USB MID driver ops. */
 static driver_ops_t mid_driver_ops = {
 	.add_device = usbmid_add_device,
 };
 
+/** USB MID driver. */
 static driver_t mid_driver = {
 	.name = NAME,
Index: uspace/drv/usbmid/usbmid.c
===================================================================
--- uspace/drv/usbmid/usbmid.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbmid/usbmid.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -67,4 +67,5 @@
 }
 
+/** DDF interface of the child - interface function. */
 static usb_iface_t child_usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
@@ -73,9 +74,10 @@
 };
 
-
+/** Operations for children - interface functions. */
 static ddf_dev_ops_t child_device_ops = {
 	.interfaces[USB_DEV_IFACE] = &child_usb_iface
 };
 
+/** Operations of the device itself. */
 static ddf_dev_ops_t mid_device_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
@@ -123,5 +125,5 @@
 /** Create new interface for USB MID device.
  *
- * @param dev Backing generic DDF child device (representing interface).
+ * @param fun Backing generic DDF device function (representing interface).
  * @param iface_no Interface number.
  * @return New interface.
Index: uspace/drv/usbmid/usbmid.h
===================================================================
--- uspace/drv/usbmid/usbmid.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/usbmid/usbmid.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -44,4 +44,5 @@
 #define NAME "usbmid"
 
+/** USB MID device container. */
 typedef struct {
 	/** Device container. */
@@ -54,4 +55,6 @@
 } usbmid_device_t;
 
+
+/** Container for single interface in a MID device. */
 typedef struct {
 	/** Function container. */
Index: uspace/drv/usbmouse/Makefile
===================================================================
--- uspace/drv/usbmouse/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/usbmouse/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I.
+
+BINARY = usbmouse
+
+SOURCES = \
+	init.c \
+	main.c \
+	mouse.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/usbmouse/init.c
===================================================================
--- uspace/drv/usbmouse/init.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/usbmouse/init.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,217 @@
+/*
+ * 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Initialization routines for USB mouse driver.
+ */
+#include "mouse.h"
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/hid.h>
+#include <usb/request.h>
+#include <errno.h>
+
+/** Mouse polling endpoint description for boot protocol subclass. */
+static usb_endpoint_description_t poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_MOUSE,
+	.flags = 0
+};
+
+/** Initialize poll pipe.
+ *
+ * Expects that session is already started on control pipe zero.
+ *
+ * @param mouse Mouse device.
+ * @param my_interface Interface number.
+ * @return Error code.
+ */
+static int intialize_poll_pipe(usb_mouse_t *mouse, int my_interface)
+{
+	assert(usb_endpoint_pipe_is_session_started(&mouse->ctrl_pipe));
+
+	int rc;
+
+	void *config_descriptor;
+	size_t config_descriptor_size;
+
+	rc = usb_request_get_full_configuration_descriptor_alloc(
+	    &mouse->ctrl_pipe, 0, &config_descriptor, &config_descriptor_size);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	usb_endpoint_mapping_t endpoint_mapping[1] = {
+		{
+			.pipe = &mouse->poll_pipe,
+			.description = &poll_endpoint_description,
+			.interface_no = my_interface
+		}
+	};
+
+	rc = usb_endpoint_pipe_initialize_from_configuration(endpoint_mapping,
+	    1, config_descriptor, config_descriptor_size, &mouse->wire);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (!endpoint_mapping[0].present) {
+		return ENOENT;
+	}
+
+	mouse->poll_interval_us = 1000 * endpoint_mapping[0].descriptor->poll_interval;
+
+	usb_log_debug("prepared polling endpoint %d (interval %zu).\n",
+	    mouse->poll_pipe.endpoint_no, mouse->poll_interval_us);
+
+	return EOK;
+}
+
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+/** Device ops for USB mouse. */
+static ddf_dev_ops_t mouse_ops = {
+	.default_handler = default_connection_handler
+};
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+
+	usb_mouse_t *mouse = (usb_mouse_t *) fun->driver_data;
+	assert(mouse != NULL);
+
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (mouse->console_phone != -1) {
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		mouse->console_phone = callback;
+		async_answer_0(icallid, EOK);
+		return;
+	}
+
+	async_answer_0(icallid, EINVAL);
+}
+
+/** Create USB mouse device.
+ *
+ * The mouse device is stored into <code>dev-&gt;driver_data</code>.
+ *
+ * @param dev Generic device.
+ * @return Error code.
+ */
+int usb_mouse_create(ddf_dev_t *dev)
+{
+	usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
+	if (mouse == NULL) {
+		return ENOMEM;
+	}
+	mouse->device = dev;
+	mouse->console_phone = -1;
+
+	int rc;
+
+	/* Initialize the backing connection. */
+	rc = usb_device_connection_initialize_from_device(&mouse->wire, dev);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	/* Initialize the default control pipe. */
+	rc = usb_endpoint_pipe_initialize_default_control(&mouse->ctrl_pipe,
+	    &mouse->wire);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	rc = usb_endpoint_pipe_start_session(&mouse->ctrl_pipe);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	rc = intialize_poll_pipe(mouse, usb_device_get_assigned_interface(dev));
+
+	/* We can ignore error here. */
+	usb_endpoint_pipe_end_session(&mouse->ctrl_pipe);
+
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	/* Create DDF function. */
+	mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
+	if (mouse->mouse_fun == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	mouse->mouse_fun->ops = &mouse_ops;
+
+	rc = ddf_fun_bind(mouse->mouse_fun);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	/* Add the function to mouse class. */
+	rc = ddf_fun_add_to_class(mouse->mouse_fun, "mouse");
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	/* Everything allright. */
+	dev->driver_data = mouse;
+	mouse->mouse_fun->driver_data = mouse;
+
+	return EOK;
+
+leave:
+	free(mouse);
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbmouse/main.c
===================================================================
--- uspace/drv/usbmouse/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/usbmouse/main.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,90 @@
+/*
+ * 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB boot protocol mouse driver.
+ */
+#include "mouse.h"
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+
+/** Callback when new mouse device is attached and recognised by DDF.
+ *
+ * @param dev Representation of a generic DDF device.
+ * @return Error code.
+ */
+static int usbmouse_add_device(ddf_dev_t *dev)
+{
+	int rc = usb_mouse_create(dev);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize device driver: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev);
+	if (poll_fibril == 0) {
+		usb_log_error("Failed to initialize polling fibril.\n");
+		/* FIXME: free allocated resources. */
+		return ENOMEM;
+	}
+
+	fibril_add_ready(poll_fibril);
+
+	usb_log_info("controlling new mouse (handle %llu).\n",
+	    dev->handle);
+
+	return EOK;
+}
+
+/** USB mouse driver ops. */
+static driver_ops_t mouse_driver_ops = {
+	.add_device = usbmouse_add_device,
+};
+
+/** USB mouse driver. */
+static driver_t mouse_driver = {
+	.name = NAME,
+	.driver_ops = &mouse_driver_ops
+};
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+
+	return ddf_driver_main(&mouse_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbmouse/mouse.c
===================================================================
--- uspace/drv/usbmouse/mouse.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/usbmouse/mouse.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,165 @@
+/*
+ * 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Actual handling of USB mouse protocol.
+ */
+#include "mouse.h"
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ipc/mouse.h>
+
+/** Fibril function for polling the mouse device.
+ *
+ * This function shall not terminate unless the device breaks and fails
+ * to send data (e.g. stalls on data request).
+ *
+ * @param arg ddf_dev_t type representing the mouse device.
+ * @return EOK Always.
+ */
+int usb_mouse_polling_fibril(void *arg)
+{
+	assert(arg != NULL);
+	ddf_dev_t *dev = (ddf_dev_t *) arg;
+	usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data;
+
+	assert(mouse);
+
+	size_t buffer_size = mouse->poll_pipe.max_packet_size;
+
+	if (buffer_size < 4) {
+		usb_log_error("Weird mouse, results will be skewed.\n");
+		buffer_size = 4;
+	}
+
+	uint8_t *buffer = malloc(buffer_size);
+	if (buffer == NULL) {
+		usb_log_error("Out of memory, poll fibril aborted.\n");
+		return ENOMEM;
+	}
+
+	while (true) {
+		async_usleep(mouse->poll_interval_us);
+
+		size_t actual_size;
+		int rc;
+
+		/*
+		 * Error checking note:
+		 * - failure when starting a session is considered
+		 *   temporary (e.g. out of phones, next try might succeed)
+		 * - failure of transfer considered fatal (probably the
+		 *   device was unplugged)
+		 * - session closing not checked (shall not fail anyway)
+		 */
+
+		rc = usb_endpoint_pipe_start_session(&mouse->poll_pipe);
+		if (rc != EOK) {
+			usb_log_warning("Failed to start session, will try again: %s.\n",
+			    str_error(rc));
+			continue;
+		}
+
+		rc = usb_endpoint_pipe_read(&mouse->poll_pipe,
+		    buffer, buffer_size, &actual_size);
+
+		usb_endpoint_pipe_end_session(&mouse->poll_pipe);
+
+		if (rc != EOK) {
+			usb_log_error("Failed reading mouse input: %s.\n",
+			    str_error(rc));
+			break;
+		}
+
+		usb_log_debug2("got buffer: %s.\n",
+		    usb_debug_str_buffer(buffer, buffer_size, 0));
+
+		uint8_t butt = buffer[0];
+		char str_buttons[4] = {
+			butt & 1 ? '#' : '.',
+			butt & 2 ? '#' : '.',
+			butt & 4 ? '#' : '.',
+			0
+		};
+
+		int shift_x = ((int) buffer[1]) - 127;
+		int shift_y = ((int) buffer[2]) - 127;
+		int wheel = ((int) buffer[3]) - 127;
+
+		if (buffer[1] == 0) {
+			shift_x = 0;
+		}
+		if (buffer[2] == 0) {
+			shift_y = 0;
+		}
+		if (buffer[3] == 0) {
+			wheel = 0;
+		}
+
+		if (mouse->console_phone >= 0) {
+			if ((shift_x != 0) || (shift_y != 0)) {
+				/* FIXME: guessed for QEMU */
+				async_req_2_0(mouse->console_phone,
+				    MEVENT_MOVE,
+				    - shift_x / 10,  - shift_y / 10);
+			}
+			if (butt) {
+				/* FIXME: proper button clicking. */
+				async_req_2_0(mouse->console_phone,
+				    MEVENT_BUTTON, 1, 1);
+				async_req_2_0(mouse->console_phone,
+				    MEVENT_BUTTON, 1, 0);
+			}
+		}
+
+		usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
+		   str_buttons, shift_x, shift_y, wheel);
+	}
+
+	/*
+	 * Device was probably unplugged.
+	 * Hang-up the phone to the console.
+	 * FIXME: release allocated memory.
+	 */
+	async_hangup(mouse->console_phone);
+	mouse->console_phone = -1;
+
+	usb_log_error("Mouse polling fibril terminated.\n");
+
+	return EOK;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/drv/usbmouse/mouse.h
===================================================================
--- uspace/drv/usbmouse/mouse.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/usbmouse/mouse.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,70 @@
+/*
+ * 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Common definitions for USB mouse driver.
+ */
+#ifndef USBMOUSE_MOUSE_H_
+#define USBMOUSE_MOUSE_H_
+
+#include <ddf/driver.h>
+#include <usb/pipes.h>
+#include <time.h>
+
+#define NAME "usbmouse"
+
+/** Container for USB mouse device. */
+typedef struct {
+	/** Generic device container. */
+	ddf_dev_t *device;
+	/** Function representing the device. */
+	ddf_fun_t *mouse_fun;
+	/** Representation of connection to the device. */
+	usb_device_connection_t wire;
+	/** Default (zero) control pipe. */
+	usb_endpoint_pipe_t ctrl_pipe;
+	/** Polling (in) pipe. */
+	usb_endpoint_pipe_t poll_pipe;
+	/** Polling interval in microseconds. */
+	suseconds_t poll_interval_us;
+	/** IPC phone to console (consumer). */
+	int console_phone;
+} usb_mouse_t;
+
+int usb_mouse_create(ddf_dev_t *);
+
+int usb_mouse_polling_fibril(void *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/usbmouse/usbmouse.ma
===================================================================
--- uspace/drv/usbmouse/usbmouse.ma	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/drv/usbmouse/usbmouse.ma	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,1 @@
+100 usb&interface&class=HID&subclass=0x01&protocol=0x02
Index: uspace/drv/vhc/conndev.c
===================================================================
--- uspace/drv/vhc/conndev.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/drv/vhc/conndev.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -110,5 +110,5 @@
 /** Callback for DDF when client disconnects.
  *
- * @param d Device the client was connected to.
+ * @param fun Device function the client was connected to.
  */
 void on_client_close(ddf_fun_t *fun)
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/c/generic/loader.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -160,4 +160,5 @@
 	int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
 	if (rc != EOK) {
+		free(pa);
 		async_wait_for(req, NULL);
 		return rc;
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -69,4 +69,5 @@
 	char *ncwd_path;
 	char *ncwd_path_nc;
+	size_t total_size; 
 
 	fibril_mutex_lock(&cwd_mutex);
@@ -77,14 +78,16 @@
 			return NULL;
 		}
-		ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
+		total_size = cwd_size + 1 + size + 1;
+		ncwd_path_nc = malloc(total_size);
 		if (!ncwd_path_nc) {
 			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
-		str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
+		str_cpy(ncwd_path_nc, total_size, cwd_path);
 		ncwd_path_nc[cwd_size] = '/';
 		ncwd_path_nc[cwd_size + 1] = '\0';
 	} else {
-		ncwd_path_nc = malloc(size + 1);
+		total_size = size + 1;
+		ncwd_path_nc = malloc(total_size);
 		if (!ncwd_path_nc) {
 			fibril_mutex_unlock(&cwd_mutex);
@@ -93,5 +96,5 @@
 		ncwd_path_nc[0] = '\0';
 	}
-	str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
+	str_append(ncwd_path_nc, total_size, path);
 	ncwd_path = canonify(ncwd_path_nc, retlen);
 	if (!ncwd_path) {
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -38,4 +38,7 @@
 	CHAR_DEV_IFACE,
 
+	/** Interface provided by any PCI device. */
+	PCI_DEV_IFACE,
+
 	/** Interface provided by any USB device. */
 	USB_DEV_IFACE,
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/drv/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -38,4 +38,5 @@
 	generic/remote_hw_res.c \
 	generic/remote_usb.c \
+	generic/remote_pci.c \
 	generic/remote_usbhc.c
 
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -43,4 +43,5 @@
 #include "remote_usb.h"
 #include "remote_usbhc.h"
+#include "remote_pci.h"
 
 static iface_dipatch_table_t remote_ifaces = {
@@ -48,4 +49,5 @@
 		&remote_hw_res_iface,
 		&remote_char_dev_iface,
+		&remote_pci_iface,
 		&remote_usb_iface,
 		&remote_usbhc_iface
Index: uspace/lib/drv/generic/remote_pci.c
===================================================================
--- uspace/lib/drv/generic/remote_pci.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/lib/drv/generic/remote_pci.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+#include <assert.h>
+#include <async.h>
+#include <errno.h>
+
+#include "pci_dev_iface.h"
+#include "ddf/driver.h"
+
+static void remote_config_space_read_8(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_config_space_read_16(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_config_space_read_32(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+
+static void remote_config_space_write_8(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_config_space_write_16(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_config_space_write_32(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+
+/** Remote USB interface operations. */
+static remote_iface_func_ptr_t remote_pci_iface_ops [] = {
+	remote_config_space_read_8,
+	remote_config_space_read_16,
+	remote_config_space_read_32,
+
+	remote_config_space_write_8,
+	remote_config_space_write_16,
+	remote_config_space_write_32
+};
+
+/** Remote USB interface structure.
+ */
+remote_iface_t remote_pci_iface = {
+	.method_count = sizeof(remote_pci_iface_ops) /
+	    sizeof(remote_pci_iface_ops[0]),
+	.methods = remote_pci_iface_ops
+};
+
+void remote_config_space_read_8(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_read_8 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint8_t value;
+	int ret = pci_iface->config_space_read_8(fun, address, &value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_1(callid, EOK, value);
+	}
+}
+
+void remote_config_space_read_16(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_read_16 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint16_t value;
+	int ret = pci_iface->config_space_read_16(fun, address, &value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_1(callid, EOK, value);
+	}
+}
+void remote_config_space_read_32(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_read_32 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint32_t value;
+	int ret = pci_iface->config_space_read_32(fun, address, &value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_1(callid, EOK, value);
+	}
+}
+
+void remote_config_space_write_8(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_write_8 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint8_t value = DEV_IPC_GET_ARG2(*call);
+	int ret = pci_iface->config_space_write_8(fun, address, value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_0(callid, EOK);
+	}
+}
+
+void remote_config_space_write_16(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_write_16 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint16_t value = DEV_IPC_GET_ARG2(*call);
+	int ret = pci_iface->config_space_write_16(fun, address, value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_0(callid, EOK);
+	}
+}
+
+void remote_config_space_write_32(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_write_32 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint32_t value = DEV_IPC_GET_ARG2(*call);
+	int ret = pci_iface->config_space_write_32(fun, address, value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_0(callid, EOK);
+	}
+}
+
+
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/include/pci_dev_iface.h
===================================================================
--- uspace/lib/drv/include/pci_dev_iface.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/lib/drv/include/pci_dev_iface.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 libdrv
+ * @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief PCI device interface definition.
+ */
+
+#ifndef LIBDRV_PCI_DEV_IFACE_H_
+#define LIBDRV_PCI_DEV_IFACE_H_
+
+#include "ddf/driver.h"
+
+typedef enum {
+	IPC_M_CONFIG_SPACE_READ_8,
+	IPC_M_CONFIG_SPACE_READ_16,
+	IPC_M_CONFIG_SPACE_READ_32,
+
+	IPC_M_CONFIG_SPACE_WRITE_8,
+	IPC_M_CONFIG_SPACE_WRITE_16,
+	IPC_M_CONFIG_SPACE_WRITE_32
+} pci_dev_iface_funcs_t;
+
+/** PCI device communication interface. */
+typedef struct {
+	int (*config_space_read_8)(ddf_fun_t *, uint32_t address, uint8_t *data);
+	int (*config_space_read_16)(ddf_fun_t *, uint32_t address, uint16_t *data);
+	int (*config_space_read_32)(ddf_fun_t *, uint32_t address, uint32_t *data);
+
+	int (*config_space_write_8)(ddf_fun_t *, uint32_t address, uint8_t data);
+	int (*config_space_write_16)(ddf_fun_t *, uint32_t address, uint16_t data);
+	int (*config_space_write_32)(ddf_fun_t *, uint32_t address, uint32_t data);
+} pci_dev_iface_t;
+
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/include/remote_pci.h
===================================================================
--- uspace/lib/drv/include/remote_pci.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
+++ uspace/lib/drv/include/remote_pci.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_PCI_H_
+#define LIBDRV_REMOTE_PCI_H_
+
+remote_iface_t remote_pci_iface;
+
+#endif
+
+/**
+ * @}
+ */
+
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/Makefile	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -47,6 +47,5 @@
 	src/request.c \
 	src/usb.c \
-	src/usbdevice.c \
-	src/usbmem.c
+	src/usbdevice.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/include/usb/classes/classes.h
===================================================================
--- uspace/lib/usb/include/usb/classes/classes.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/include/usb/classes/classes.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief USB device classes and subclasses.
+ * USB device classes (generic constants and functions).
  */
 #ifndef LIBUSB_CLASSES_H_
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/include/usb/debug.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Debugging related functions.
+ * Debugging related functions.
  */
 #ifndef LIBUSB_DEBUG_H_
@@ -39,7 +39,4 @@
 #include <assert.h>
 
-void usb_dprintf(const char *tag, int level, const char *format, ...);
-void usb_dprintf_enable(const char *tag, int level);
-
 void usb_dump_standard_descriptor(FILE *, const char *, const char *,
     const uint8_t *, size_t);
@@ -47,10 +44,36 @@
 /** Logging level. */
 typedef enum {
+	/** Fatal, unrecoverable, error.
+	 * Such error prevents the driver from working at all.
+	 */
 	USB_LOG_LEVEL_FATAL,
+
+	/** Serious but recoverable error
+	 * Shall be used for errors fatal for single device but not for
+	 * driver itself.
+	 */
 	USB_LOG_LEVEL_ERROR,
+
+	/** Warning.
+	 * Problems from which the driver is able to recover gracefully.
+	 */
 	USB_LOG_LEVEL_WARNING,
+
+	/** Information message.
+	 * This should be the last level that is printed by default to
+	 * the screen.
+	 * Typical usage is to inform that new device was found and what
+	 * are its capabilities.
+	 * Do not use for repetitive actions (such as device polling).
+	 */
 	USB_LOG_LEVEL_INFO,
+
+	/** Debugging message. */
 	USB_LOG_LEVEL_DEBUG,
+
+	/** More detailed debugging message. */
 	USB_LOG_LEVEL_DEBUG2,
+
+	/** Terminating constant for logging levels. */
 	USB_LOG_LEVEL_MAX
 } usb_log_level_t;
@@ -61,22 +84,29 @@
 void usb_log_printf(usb_log_level_t, const char *, ...);
 
+/** Log fatal error. */
 #define usb_log_fatal(format, ...) \
 	usb_log_printf(USB_LOG_LEVEL_FATAL, format, ##__VA_ARGS__)
 
+/** Log normal (recoverable) error. */
 #define usb_log_error(format, ...) \
 	usb_log_printf(USB_LOG_LEVEL_ERROR, format, ##__VA_ARGS__)
 
+/** Log warning. */
 #define usb_log_warning(format, ...) \
 	usb_log_printf(USB_LOG_LEVEL_WARNING, format, ##__VA_ARGS__)
 
+/** Log informational message. */
 #define usb_log_info(format, ...) \
 	usb_log_printf(USB_LOG_LEVEL_INFO, format, ##__VA_ARGS__)
 
+/** Log debugging message. */
 #define usb_log_debug(format, ...) \
 	usb_log_printf(USB_LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
 
+/** Log verbose debugging message. */
 #define usb_log_debug2(format, ...) \
 	usb_log_printf(USB_LOG_LEVEL_DEBUG2, format, ##__VA_ARGS__)
 
+const char *usb_debug_str_buffer(const uint8_t *, size_t, size_t);
 
 
Index: uspace/lib/usb/include/usb/descriptor.h
===================================================================
--- uspace/lib/usb/include/usb/descriptor.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/include/usb/descriptor.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Standard USB descriptors.
+ * Standard USB descriptors.
  */
 #ifndef LIBUSB_DESCRIPTOR_H_
@@ -83,5 +83,5 @@
 	/** Product descriptor index. */
 	uint8_t str_product;
-	/** Device serial number desriptor index. */
+	/** Device serial number descriptor index. */
 	uint8_t str_serial_number;
 	/** Number of possible configurations. */
@@ -167,7 +167,4 @@
 } __attribute__ ((packed)) usb_standard_endpoint_descriptor_t;
 
-
-/* TODO: string descriptors. */
-
 #endif
 /**
Index: uspace/lib/usb/include/usb/dp.h
===================================================================
--- uspace/lib/usb/include/usb/dp.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/include/usb/dp.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief USB descriptor parser.
+ * USB descriptor parser.
  */
 #ifndef LIBUSB_DP_H_
@@ -40,6 +40,15 @@
 #include <usb/descriptor.h>
 
+/** USB descriptors nesting.
+ * The nesting describes the logical tree USB descriptors form
+ * (e.g. that endpoint descriptor belongs to interface or that
+ * interface belongs to configuration).
+ *
+ * See usb_descriptor_type_t for descriptor constants.
+ */
 typedef struct {
+	/** Child descriptor id. */
 	int child;
+	/** Parent descriptor id. */
 	int parent;
 } usb_dp_descriptor_nesting_t;
@@ -47,11 +56,17 @@
 extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
 
+/** Descriptor parser structure. */
 typedef struct {
+	/** Used descriptor nesting. */
 	usb_dp_descriptor_nesting_t *nesting;
 } usb_dp_parser_t;
 
+/** Descriptor parser data. */
 typedef struct {
+	/** Data to be parsed. */
 	uint8_t *data;
+	/** Size of input data in bytes. */
 	size_t size;
+	/** Custom argument. */
 	void *arg;
 } usb_dp_parser_data_t;
Index: uspace/lib/usb/include/usb/hub.h
===================================================================
--- uspace/lib/usb/include/usb/hub.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/include/usb/hub.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -32,4 +32,6 @@
 /** @file
  * Functions needed by hub drivers.
+ *
+ * For class specific requests, see usb/classes/hub.h.
  */
 #ifndef LIBUSB_HUB_H_
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/include/usb/pipes.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -43,6 +43,5 @@
 #include <ddf/driver.h>
 
-/**
- * Abstraction of a physical connection to the device.
+/** Abstraction of a physical connection to the device.
  * This type is an abstraction of the USB wire that connects the host and
  * the function (device).
@@ -55,6 +54,5 @@
 } usb_device_connection_t;
 
-/**
- * Abstraction of a logical connection to USB device endpoint.
+/** Abstraction of a logical connection to USB device endpoint.
  * It encapsulates endpoint attributes (transfer type etc.) as well
  * as information about currently running sessions.
@@ -111,5 +109,5 @@
 	/** Found descriptor fitting the description. */
 	usb_standard_endpoint_descriptor_t *descriptor;
-	/** Interface the endpoint belongs to. */
+	/** Interface descriptor the endpoint belongs to. */
 	usb_standard_interface_descriptor_t *interface;
 	/** Whether the endpoint was actually found. */
Index: uspace/lib/usb/include/usb/request.h
===================================================================
--- uspace/lib/usb/include/usb/request.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/include/usb/request.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -72,5 +72,5 @@
 	union {
 		uint16_t value;
-		/* FIXME: add #ifdefs according to host endianess */
+		/* FIXME: add #ifdefs according to host endianness */
 		struct {
 			uint8_t value_low;
@@ -106,4 +106,6 @@
 int usb_request_get_full_configuration_descriptor(usb_endpoint_pipe_t *, int,
     void *, size_t, size_t *);
+int usb_request_get_full_configuration_descriptor_alloc(usb_endpoint_pipe_t *,
+    int, void **, size_t *);
 int usb_request_set_configuration(usb_endpoint_pipe_t *, uint8_t);
 
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/include/usb/usb.h	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Base USB types.
+ * Common USB types and functions.
  */
 #ifndef LIBUSB_USB_H_
@@ -121,4 +121,10 @@
 } usb_target_t;
 
+/** Compare USB targets (addresses and endpoints).
+ *
+ * @param a First target.
+ * @param b Second target.
+ * @return Whether @p a and @p b points to the same pipe on the same device.
+ */
 static inline int usb_target_same(usb_target_t a, usb_target_t b)
 {
Index: pace/lib/usb/include/usb/usbmem.h
===================================================================
--- uspace/lib/usb/include/usb/usbmem.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ 	(revision )
@@ -1,81 +1,0 @@
-/*
- * Copyright (c) 2011 Matus Dekanek
- * 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.
- */
-
-#ifndef USBMEM_H
-#define	USBMEM_H
-
-
-// group should be changed - this is not usb specific
-/** @addtogroup usb
- * @{
- */
-/** @file definitions of memory management with address translation, used mostly in usb stack
- *
- * USB HCD needs traslation between physical and virtual addresses. These
- * functions implement such functionality. For each allocated virtual address
- * the memory manager gets also it`s physical translation and remembers it.
- * Addresses allocated byt this manager can be therefore translated from and to
- * physical addresses.
- * Typical use:
- * void * address = mman_malloc(some_size);
- * void * physical_address = mman_getPA(address);
- * void * the_same_address = mman_getVA(physical_address);
- * void * null_address = mman_getPA(non_existing_address);
- * mman_free(address);
- * // physical_address, adress and the_same_address are no longer valid here
- *
- *
- * @note Addresses allocated by this memory manager should be as well
- * deallocated byt it.
- *
- */
-
-#include <sys/types.h>
-
-extern void * mman_malloc(
-    size_t size,
-    size_t alignment,
-    unsigned long max_physical_address);
-
-extern void * mman_getVA(void * addr);
-
-extern void * mman_getPA(void * addr);
-
-extern void mman_free(void * addr);
-
-
-
-
-
-
-/** @}
- */
-
-
-#endif	/* USBMEM_H */
-
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/ddfiface.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -56,5 +56,5 @@
 /** Get host controller handle, interface implementation for hub driver.
  *
- * @param[in] device Device the operation is running on.
+ * @param[in] fun Device function the operation is running on.
  * @param[out] handle Storage for the host controller handle.
  * @return Error code.
@@ -69,5 +69,5 @@
  * a hub driver.
  *
- * @param[in] device Device the operation is running on.
+ * @param[in] fun Device function the operation is running on.
  * @param[out] handle Storage for the host controller handle.
  * @return Error code.
@@ -88,4 +88,6 @@
 	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &hc_handle);
 
+	async_hangup(parent_phone);
+
 	if (rc != EOK) {
 		return rc;
@@ -99,5 +101,5 @@
 /** Get host controller handle, interface implementation for HC driver.
  *
- * @param[in] device Device the operation is running on.
+ * @param[in] fun Device function the operation is running on.
  * @param[out] handle Storage for the host controller handle.
  * @return Always EOK.
@@ -116,5 +118,5 @@
 /** Get USB device address, interface implementation for hub driver.
  *
- * @param[in] device Device the operation is running on.
+ * @param[in] fun Device function the operation is running on.
  * @param[in] handle Devman handle of USB device we want address of.
  * @param[out] address Storage for USB address of device with handle @p handle.
@@ -151,5 +153,5 @@
  * a hub driver.
  *
- * @param[in] device Device the operation is running on.
+ * @param[in] fun Device function the operation is running on.
  * @param[in] handle Devman handle of USB device we want address of.
  * @param[out] address Storage for USB address of device with handle @p handle.
Index: uspace/lib/usb/src/debug.c
===================================================================
--- uspace/lib/usb/src/debug.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/debug.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Debugging support.
+ * Debugging and logging support.
  */
 #include <adt/list.h>
@@ -40,126 +40,16 @@
 #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);
-
 /** Level of logging messages. */
 static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
+
 /** Prefix for logging messages. */
 static const char *log_prefix = "usb";
+
 /** Serialization mutex for logging functions. */
 static FIBRIL_MUTEX_INITIALIZE(log_serializer);
+
+/** File where to store the log. */
 static FILE *log_stream = NULL;
 
-/** 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);
-}
 
 /** Enable logging.
@@ -182,5 +72,9 @@
 }
 
-
+/** Get log level name prefix.
+ *
+ * @param level Log level.
+ * @return String prefix for the message.
+ */
 static const char *log_level_name(usb_log_level_t level)
 {
@@ -252,4 +146,115 @@
 }
 
+
+#define REMAINDER_STR_FMT " (%zu)..."
+/* string + terminator + number width (enough for 4GB)*/
+#define REMAINDER_STR_LEN (5 + 1 + 10)
+
+/** How many bytes to group together. */
+#define BUFFER_DUMP_GROUP_SIZE 4
+
+/** Size of the string for buffer dumps. */
+#define BUFFER_DUMP_LEN 240 /* Ought to be enough for everybody ;-). */
+
+/** Fibril local storage for the dumped buffer. */
+static fibril_local char buffer_dump[BUFFER_DUMP_LEN];
+
+/** Dump buffer into string.
+ *
+ * The function dumps given buffer into hexadecimal format and stores it
+ * in a static fibril local string.
+ * That means that you do not have to deallocate the string (actually, you
+ * can not do that) and you do not have to guard it against concurrent
+ * calls to it.
+ * The only limitation is that each call rewrites the buffer again.
+ * Thus, it is necessary to copy the buffer elsewhere (that includes printing
+ * to screen or writing to file).
+ * Since this function is expected to be used for debugging prints only,
+ * that is not a big limitation.
+ *
+ * @warning You cannot use this function twice in the same printf
+ * (see detailed explanation).
+ *
+ * @param buffer Buffer to be printed (can be NULL).
+ * @param size Size of the buffer in bytes (can be zero).
+ * @param dumped_size How many bytes to actually dump (zero means all).
+ * @return Dumped buffer as a static (but fibril local) string.
+ */
+const char *usb_debug_str_buffer(const uint8_t *buffer, size_t size,
+    size_t dumped_size)
+{
+	/*
+	 * Remove previous string (that might also reveal double usage of
+	 * this function).
+	 */
+	bzero(buffer_dump, BUFFER_DUMP_LEN);
+
+	if (buffer == NULL) {
+		return "(null)";
+	}
+	if (size == 0) {
+		return "(empty)";
+	}
+	if ((dumped_size == 0) || (dumped_size > size)) {
+		dumped_size = size;
+	}
+
+	/* How many bytes are available in the output buffer. */
+	size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;
+	char *it = buffer_dump;
+
+	size_t index = 0;
+
+	while (index < size) {
+		/* Determine space before the number. */
+		const char *space_before;
+		if (index == 0) {
+			space_before = "";
+		} else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
+			space_before = "  ";
+		} else {
+			space_before = " ";
+		}
+
+		/*
+		 * Add the byte as a hexadecimal number plus the space.
+		 * We do it into temporary buffer to ensure that always
+		 * the whole byte is printed.
+		 */
+		int val = buffer[index];
+		char current_byte[16];
+		int printed = snprintf(current_byte, 16,
+		    "%s%02x", space_before, val);
+		if (printed < 0) {
+			break;
+		}
+
+		if ((size_t) printed > buffer_remaining_size) {
+			break;
+		}
+
+		/* We can safely add 1, because space for end 0 is reserved. */
+		str_append(it, buffer_remaining_size + 1, current_byte);
+
+		buffer_remaining_size -= printed;
+		/* Point at the terminator 0. */
+		it += printed;
+		index++;
+
+		if (index >= dumped_size) {
+			break;
+		}
+	}
+
+	/* Add how many bytes were not printed. */
+	if (index < size) {
+		snprintf(it, REMAINDER_STR_LEN,
+		    REMAINDER_STR_FMT, size - index);
+	}
+
+	return buffer_dump;
+}
+
+
 /**
  * @}
Index: uspace/lib/usb/src/dp.c
===================================================================
--- uspace/lib/usb/src/dp.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/dp.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -32,5 +32,12 @@
 /**
  * @file
- * @brief USB descriptor parser (implementation).
+ * USB descriptor parser (implementation).
+ *
+ * The descriptor parser is a generic parser for structure, where individual
+ * items are stored in single buffer and each item begins with length followed
+ * by type. These types are organized into tree hierarchy.
+ *
+ * The parser is able of only two actions: find first child and find next
+ * sibling.
  */
 #include <stdio.h>
Index: uspace/lib/usb/src/dump.c
===================================================================
--- uspace/lib/usb/src/dump.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/dump.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Descriptor dumping.
+ * Descriptor dumping.
  */
 #include <adt/list.h>
@@ -43,6 +43,9 @@
 #include <usb/classes/hid.h>
 
+/** Mapping between descriptor id and dumping function. */
 typedef struct {
+	/** Descriptor id. */
 	int id;
+	/** Dumping function. */
 	void (*dump)(FILE *, const char *, const char *,
 	    const uint8_t *, size_t);
@@ -66,4 +69,5 @@
     const uint8_t *, size_t);
 
+/** Descriptor dumpers mapping. */
 static descriptor_dump_t descriptor_dumpers[] = {
 	{ USB_DESCTYPE_DEVICE, usb_dump_descriptor_device },
@@ -273,4 +277,5 @@
     const uint8_t *descriptor, size_t descriptor_length)
 {
+	/* TODO */
 }
 
@@ -279,4 +284,5 @@
     const uint8_t *descriptor, size_t descriptor_length)
 {
+	/* TODO */
 }
 
Index: pace/lib/usb/src/hcdhubd_private.h
===================================================================
--- uspace/lib/usb/src/hcdhubd_private.h	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ 	(revision )
@@ -1,77 +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 libusb
- * @{
- */
-/** @file
- * @brief Common definitions for both HC driver and hub driver.
- */
-#ifndef LIBUSB_HCDHUBD_PRIVATE_H_
-#define LIBUSB_HCDHUBD_PRIVATE_H_
-
-#define USB_HUB_DEVICE_NAME "usbhub"
-#define USB_KBD_DEVICE_NAME "hid"
-
-extern link_t hc_list;
-extern usb_hc_driver_t *hc_driver;
-
-extern usbhc_iface_t usbhc_interface;
-
-usb_address_t usb_get_address_by_handle(devman_handle_t);
-int usb_add_hc_device(device_t *);
-
-/** lowest allowed usb address */
-extern int usb_lowest_address;
-
-/** highest allowed usb address */
-extern int usb_highest_address;
-
-/**
- * @brief initialize address list of given hcd
- *
- * This function should be used only for hcd initialization.
- * It creates interval list of free addresses, thus it is initialized as
- * list with one interval with whole address space. Using an address shrinks
- * the interval, freeing an address extends an interval or creates a
- * new one. 
- *
- * @param hcd
- * @return
- */
-void  usb_create_address_list(usb_hc_device_t * hcd);
-
-
-
-
-
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/usb/src/hub.c
===================================================================
--- uspace/lib/usb/src/hub.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/hub.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -57,4 +57,5 @@
  *
  * @param connection Opened connection to host controller.
+ * @param speed Speed of the device that will respond on the default address.
  * @return Error code.
  */
@@ -86,4 +87,6 @@
  *
  * @param connection Opened connection to host controller.
+ * @param speed Speed of the new device (device that will be assigned
+ *    the returned address).
  * @return Assigned USB address or negative error code.
  */
@@ -144,5 +147,5 @@
 /** Wrapper for registering attached device to the hub.
  *
- * The @p enable_port function is expected to enable singalling on given
+ * The @p enable_port function is expected to enable signaling on given
  * port.
  * The two arguments to it can have arbitrary meaning
@@ -152,17 +155,22 @@
  *
  * If the @p enable_port fails (i.e. does not return EOK), the device
- * addition is cancelled.
+ * addition is canceled.
  * The return value is then returned (it is good idea to use different
  * error codes than those listed as return codes by this function itself).
  *
- * @param parent Parent device (i.e. the hub device).
- * @param connection Opened connection to host controller.
- * @param dev_speed New device speed.
- * @param enable_port Function for enabling signalling through the port the
+ * @param[in] parent Parent device (i.e. the hub device).
+ * @param[in] connection Opened connection to host controller.
+ * @param[in] dev_speed New device speed.
+ * @param[in] enable_port Function for enabling signaling through the port the
  *	device is attached to.
- * @param port_no Port number (passed through to @p enable_port).
- * @param arg Any data argument to @p enable_port.
+ * @param[in] port_no Port number (passed through to @p enable_port).
+ * @param[in] arg Any data argument to @p enable_port.
  * @param[out] assigned_address USB address of the device.
  * @param[out] assigned_handle Devman handle of the new device.
+ * @param[in] dev_ops Child device ops.
+ * @param[in] new_dev_data Arbitrary pointer to be stored in the child
+ *	as @c driver_data.
+ * @param[out] new_fun Storage where pointer to allocated child function
+ *	will be written.
  * @return Error code.
  * @retval ENOENT Connection to HC not opened.
@@ -201,5 +209,5 @@
 
 	/*
-	 * Enable the port (i.e. allow signalling through this port).
+	 * Enable the port (i.e. allow signaling through this port).
 	 */
 	rc = enable_port(port_no, arg);
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/pipes.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -99,5 +99,5 @@
  *
  * @param connection Connection structure to be initialized.
- * @param device Generic device backing the USB device.
+ * @param dev Generic device backing the USB device.
  * @return Error code.
  */
Index: uspace/lib/usb/src/pipesio.c
===================================================================
--- uspace/lib/usb/src/pipesio.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/pipesio.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -115,5 +115,10 @@
 
 	if (data_request_rc != EOK) {
-		return (int) data_request_rc;
+		/* 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) {
@@ -331,5 +336,10 @@
 
 	if (data_request_rc != EOK) {
-		return (int) data_request_rc;
+		/* 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) {
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/recognise.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Functions for recognising kind of attached devices.
+ * Functions for recognition of attached devices.
  */
 #include <sys/types.h>
@@ -44,15 +44,22 @@
 #include <assert.h>
 
+/** Index to append after device name for uniqueness. */
 static size_t device_name_index = 0;
+/** Mutex guard for device_name_index. */
 static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
 
+/** DDF operations of child devices. */
 ddf_dev_ops_t child_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
 };
 
+/** Get integer part from BCD coded number. */
 #define BCD_INT(a) (((unsigned int)(a)) / 256)
+/** Get fraction part from BCD coded number (as an integer, no less). */
 #define BCD_FRAC(a) (((unsigned int)(a)) % 256)
 
+/** Format for BCD coded number to be used in printf. */
 #define BCD_FMT "%x.%x"
+/** Arguments to printf for BCD coded number. */
 #define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
 
@@ -113,4 +120,11 @@
 }
 
+/** Add match id to list or return with error code.
+ *
+ * @param match_ids List of match ids.
+ * @param score Match id score.
+ * @param format Format of the matching string
+ * @param ... Arguments for the format.
+ */
 #define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
 	do { \
@@ -124,9 +138,10 @@
 /** Create device match ids based on its interface.
  *
- * @param[in] descriptor Interface descriptor.
+ * @param[in] desc_device Device descriptor.
+ * @param[in] desc_interface Interface descriptor.
  * @param[out] matches Initialized list of match ids.
  * @return Error code (the two mentioned are not the only ones).
  * @retval EINVAL Invalid input parameters (expects non NULL pointers).
- * @retval ENOENT Interface does not specify class.
+ * @retval ENOENT Device class is not "use interface".
  */
 int usb_device_create_match_ids_from_interface(
@@ -319,4 +334,9 @@
  * @param[in] parent Parent device.
  * @param[out] child_handle Handle of the child device.
+ * @param[in] dev_ops Child device ops.
+ * @param[in] dev_data Arbitrary pointer to be stored in the child
+ *	as @c driver_data.
+ * @param[out] child_fun Storage where pointer to allocated child function
+ *	will be written.
  * @return Error code.
  */
Index: uspace/lib/usb/src/request.c
===================================================================
--- uspace/lib/usb/src/request.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/request.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -110,5 +110,5 @@
   *	(must be in USB endianness).
   * @param data Buffer where to store data accepted during the DATA stage.
-  *	(they will come in USB endianess).
+  *	(they will come in USB endianness).
   * @param data_size Size of the @p data buffer
   * 	(in native endianness).
@@ -161,10 +161,4 @@
  * the new address.
  *
- * @see usb_drv_reserve_default_address
- * @see usb_drv_release_default_address
- * @see usb_drv_request_address
- * @see usb_drv_release_address
- * @see usb_drv_bind_address
- *
  * @param pipe Control endpoint pipe (session must be already started).
  * @param new_address New USB address to be set (in native endianness).
@@ -201,4 +195,5 @@
  * @param[in] pipe Control endpoint pipe (session must be already started).
  * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] recipient Request recipient (device/interface/endpoint).
  * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
  * @param[in] descriptor_index Descriptor index.
@@ -235,4 +230,5 @@
  * @param[in] pipe Control endpoint pipe (session must be already started).
  * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] recipient Request recipient (device/interface/endpoint).
  * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
  * @param[in] descriptor_index Descriptor index.
@@ -412,4 +408,69 @@
 }
 
+/** Retrieve full configuration descriptor, allocate space for it.
+ *
+ * The function takes care that full configuration descriptor is returned
+ * (i.e. the function will fail when less data then descriptor.totalLength
+ * is returned).
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Configuration index.
+ * @param[out] descriptor_ptr Where to store pointer to allocated buffer.
+ * @param[out] descriptor_size Where to store the size of the descriptor.
+ * @return Error code.
+ */
+int usb_request_get_full_configuration_descriptor_alloc(
+    usb_endpoint_pipe_t *pipe, int index,
+    void **descriptor_ptr, size_t *descriptor_size)
+{
+	int rc;
+
+	if (descriptor_ptr == NULL) {
+		return EBADMEM;
+	}
+
+	usb_standard_configuration_descriptor_t bare_config;
+	rc = usb_request_get_bare_configuration_descriptor(pipe, index,
+	    &bare_config);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (bare_config.descriptor_type != USB_DESCTYPE_CONFIGURATION) {
+		return ENOENT;
+	}
+	if (bare_config.total_length < sizeof(bare_config)) {
+		return ELIMIT;
+	}
+
+	void *buffer = malloc(bare_config.total_length);
+	if (buffer == NULL) {
+		return ENOMEM;
+	}
+
+	size_t transferred = 0;
+	rc = usb_request_get_full_configuration_descriptor(pipe, index,
+	    buffer, bare_config.total_length, &transferred);
+	if (rc != EOK) {
+		free(buffer);
+		return rc;
+	}
+
+	if (transferred != bare_config.total_length) {
+		free(buffer);
+		return ELIMIT;
+	}
+
+	/* Everything looks okay, copy the pointers. */
+
+	*descriptor_ptr = buffer;
+
+	if (descriptor_size != NULL) {
+		*descriptor_size = bare_config.total_length;
+	}
+
+	return EOK;
+}
+
 /** Set configuration of USB device.
  *
@@ -463,5 +524,5 @@
 		return EEMPTY;
 	}
-	/* Substract first 2 bytes (length and descriptor type). */
+	/* Subtract first 2 bytes (length and descriptor type). */
 	string_descriptor_size -= 2;
 
@@ -483,5 +544,5 @@
 	size_t i;
 	for (i = 0; i < langs_count; i++) {
-		/* Language code from the descriptor is in USB endianess. */
+		/* Language code from the descriptor is in USB endianness. */
 		/* FIXME: is this really correct? */
 		uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8)
@@ -504,6 +565,7 @@
  *
  * @param[in] pipe Control endpoint pipe (session must be already started).
- * @param[in] index String index (in native endianess).
- * @param[in] lang String language (in native endianess).
+ * @param[in] index String index (in native endianness),
+ *	first index has number 1 (index from descriptors can be used directly).
+ * @param[in] lang String language (in native endianness).
  * @param[out] string_ptr Where to store allocated string in native encoding.
  * @return Error code.
@@ -515,6 +577,9 @@
 		return EBADMEM;
 	}
-	/* Index is actually one byte value. */
-	if (index > 0xFF) {
+	/*
+	 * Index is actually one byte value and zero index is used
+	 * to retrieve list of supported languages.
+	 */
+	if ((index < 1) || (index > 0xFF)) {
 		return ERANGE;
 	}
@@ -544,5 +609,5 @@
 		goto leave;
 	}
-	/* Substract first 2 bytes (length and descriptor type). */
+	/* Subtract first 2 bytes (length and descriptor type). */
 	string_size -= 2;
 
Index: uspace/lib/usb/src/usb.c
===================================================================
--- uspace/lib/usb/src/usb.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/lib/usb/src/usb.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Base USB types.
+ * Common USB functions.
  */
 #include <usb/usb.h>
@@ -37,5 +37,9 @@
 
 
-/** String representation for USB transfer type. */
+/** String representation for USB transfer type.
+ *
+ * @param t Transfer type.
+ * @return Transfer type as a string (in English).
+ */
 const char * usb_str_transfer_type(usb_transfer_type_t t)
 {
Index: pace/lib/usb/src/usbmem.c
===================================================================
--- uspace/lib/usb/src/usbmem.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ 	(revision )
@@ -1,201 +1,0 @@
-/*
- * Copyright (c) 2011 Matus Dekanek
- * 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 libc
- * @{
- */
-/** @file implementation of special memory management, used mostly in usb stack
- */
-
-#include <adt/hash_table.h>
-#include <adt/list.h>
-#include <as.h>
-#include <errno.h>
-#include <malloc.h>
-
-#include "usb/usbmem.h"
-
-#define ADDR_BUCKETS 1537
-
-//address translation tables
-static hash_table_t * pa2va_table = NULL;
-static hash_table_t * va2pa_table = NULL;
-
-/**
- * address translation hashtable item
- */
-typedef struct{
-	unsigned long addr;
-	unsigned long translation;
-	link_t link;
-
-}addr_node_t;
-
-static hash_index_t addr_hash(unsigned long key[])
-{
-	return (3*key[0]<<4) % ADDR_BUCKETS;
-}
-
-static int addr_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	addr_node_t *addr_node = hash_table_get_instance(item, addr_node_t, link);
-	return (addr_node->addr == key[0]);
-}
-
-static void addr_remove_callback(link_t * item)
-{
-	//delete item
-	addr_node_t *addr_node = hash_table_get_instance(item, addr_node_t, link);
-	free(addr_node);
-}
-
-
-static hash_table_operations_t addr_devices_ops = {
-	.hash = addr_hash,
-	.compare = addr_compare,
-	.remove_callback = addr_remove_callback
-};
-
-/**
- * create node for address translation hashtable
- * @param addr
- * @param translation
- * @return
- */
-static addr_node_t * create_addr_node(void * addr, void * translation){
-	addr_node_t * node = (addr_node_t*)malloc(sizeof(addr_node_t));
-	node->addr = (unsigned long)addr;
-	node->translation = (unsigned long)translation;
-	return node;
-}
-
-/**
- * allocate size on heap and register it`s pa<->va translation
- *
- * If physical address + size is 2GB or higher, nothing is allocated and NULL
- * is returned.
- * @param size
- * @param alignment
- * @return
- */
-void * mman_malloc(
-	size_t size,
-	size_t alignment,
-	unsigned long max_physical_address)
-{
-	if (size == 0)
-		return NULL;
-	if (alignment == 0)
-		return NULL;
-	//check if tables were initialized
-	if(!pa2va_table){
-		pa2va_table = (hash_table_t*)malloc(sizeof(hash_table_t*));
-		va2pa_table = (hash_table_t*)malloc(sizeof(hash_table_t*));
-		hash_table_create(pa2va_table, ADDR_BUCKETS, 1,
-		    &addr_devices_ops);
-		hash_table_create(va2pa_table, ADDR_BUCKETS, 1,
-		    &addr_devices_ops);
-	}
-	//allocate
-	void * vaddr = memalign(alignment, size);
-	
-	//get translation
-	void * paddr = NULL;
-	int opResult = as_get_physical_mapping(vaddr,(uintptr_t*)&paddr);
-	if(opResult != EOK){
-		//something went wrong
-		free(vaddr);
-		return NULL;
-	}
-	if((unsigned long)paddr + size > max_physical_address){
-		//unusable address for usb
-		free(vaddr);
-		return NULL;
-	}
-	//store translation
-	addr_node_t * pa2vaNode = create_addr_node(paddr,vaddr);
-	addr_node_t * va2paNode = create_addr_node(vaddr,paddr);
-
-	unsigned long keypaddr = (unsigned long)paddr;
-	unsigned long keyvaddr = (unsigned long)vaddr;
-	hash_table_insert(pa2va_table, (&keypaddr), &pa2vaNode->link);
-	hash_table_insert(va2pa_table, (&keyvaddr), &va2paNode->link);
-	//return
-	return vaddr;
-
-}
-
-/**
- * get virtual address from physical
- * @param addr
- * @return translated virtual address or null
- */
-void * mman_getVA(void * addr){
-	unsigned long keypaddr = (unsigned long)addr;
-	link_t * link = hash_table_find(pa2va_table, &keypaddr);
-	if(!link) return NULL;
-	addr_node_t * node = hash_table_get_instance(link, addr_node_t, link);
-	return (void*)node->translation;
-}
-
-/**
- * get physical address from virtual
- * @param addr
- * @return physical address or null
- */
-void * mman_getPA(void * addr){
-	unsigned long keyvaddr = (unsigned long)addr;
-	link_t * link = hash_table_find(va2pa_table, &keyvaddr);
-	if(!link) return NULL;
-	addr_node_t * node = hash_table_get_instance(link, addr_node_t, link);
-	return (void*)node->translation;
-}
-
-/**
- * free the address and deregister it from pa<->va translation
- * @param vaddr if NULL, nothing happens
- */
-void mman_free(void * vaddr){
-	if(!vaddr)
-		return;
-	//get paddress
-	void * paddr = mman_getPA(vaddr);
-	unsigned long keypaddr = (unsigned long)paddr;
-	unsigned long keyvaddr = (unsigned long)vaddr;
-	//remove mapping
-	hash_table_remove(pa2va_table,&keypaddr, 1);
-	hash_table_remove(va2pa_table,&keyvaddr, 1);
-	//free address
-	free(vaddr);
-}
-
-
-
-/** @}
- */
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/srv/devmap/devmap.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -123,4 +123,10 @@
 static devmap_handle_t last_handle = 0;
 static devmap_device_t *null_devices[NULL_DEVICES];
+
+/*
+ * Dummy list for null devices. This is necessary so that null devices can
+ * be used just as any other devices, e.g. in devmap_device_unregister_core().
+ */
+static LIST_INITIALIZE(dummy_null_driver_devices);
 
 static devmap_handle_t devmap_create_handle(void)
@@ -953,7 +959,11 @@
 	device->name = dev_name;
 	
-	/* Insert device into list of all devices
-	   and into null devices array */
+	/*
+	 * Insert device into list of all devices and into null devices array.
+	 * Insert device into a dummy list of null driver's devices so that it
+	 * can be safely removed later.
+	 */
 	list_append(&device->devices, &devices_list);
+	list_append(&device->driver_devices, &dummy_null_driver_devices);
 	null_devices[i] = device;
 	
Index: uspace/srv/fs/fat/fat_dentry.c
===================================================================
--- uspace/srv/fs/fat/fat_dentry.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/srv/fs/fat/fat_dentry.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -42,5 +42,5 @@
 static bool is_d_char(const char ch)
 {
-	if (isalnum(ch) || ch == '_')
+	if (isalnum(ch) || ch == '_' || ch == '-')
 		return true;
 	else
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -325,4 +325,5 @@
 		    uint16_t_le2host(d->firstc));
 		if (rc != EOK) {
+			(void) block_put(b);
 			(void) fat_node_put(FS_NODE(nodep));
 			return rc;
@@ -811,4 +812,5 @@
 	fibril_mutex_unlock(&childp->idx->lock);
 	childp->lnkcnt = 0;
+	childp->refcnt++;	/* keep the node in memory until destroyed */
 	childp->dirty = true;
 	fibril_mutex_unlock(&childp->lock);
@@ -1488,4 +1490,5 @@
 	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
 	fs_node_t *fn;
+	fat_node_t *nodep;
 	int rc;
 
@@ -1499,4 +1502,11 @@
 		return;
 	}
+
+	nodep = FAT_NODE(fn);
+	/*
+	 * We should have exactly two references. One for the above
+	 * call to fat_node_get() and one from fat_unlink().
+	 */
+	assert(nodep->refcnt == 2);
 
 	rc = fat_destroy_node(fn);
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 60a228fd7f87439364d5a1c15b71834ad60945c0)
+++ uspace/srv/hid/console/console.c	(revision 7351dc3dbe011ce085a1813b4acde57432b7fc0e)
@@ -41,4 +41,5 @@
 #include <ipc/ns.h>
 #include <errno.h>
+#include <str_error.h>
 #include <ipc/console.h>
 #include <unistd.h>
@@ -64,4 +65,6 @@
 #define NAME       "console"
 #define NAMESPACE  "term"
+/** Interval for checking for new keyboard (1/4s). */
+#define HOTPLUG_WATCH_INTERVAL (1000 * 250)
 
 /** Phone to the keyboard driver. */
@@ -712,5 +715,6 @@
 }
 
-static int connect_keyboard(char *path)
+static int connect_keyboard_or_mouse(const char *devname,
+    async_client_conn_t handler, const char *path)
 {
 	int fd = open(path, O_RDONLY);
@@ -725,96 +729,53 @@
 	}
 	
-	/* NB: The callback connection is slotted for removal */
-	sysarg_t phonehash;
-	sysarg_t taskhash;
-	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, SERVICE_CONSOLE,
-	    0, 0, NULL, NULL, NULL, &taskhash, &phonehash);
+	int rc = async_connect_to_me(phone, SERVICE_CONSOLE, 0, 0, handler);
 	if (rc != EOK) {
-		printf(NAME ": Failed to create callback from input device\n");
+		printf(NAME ": " \
+		    "Failed to create callback from input device: %s.\n",
+		    str_error(rc));
 		return rc;
 	}
 	
-	async_new_connection(taskhash, phonehash, 0, NULL, keyboard_events);
-
-	printf(NAME ": we got a hit (new keyboard \"%s\").\n", path);
+	printf(NAME ": found %s \"%s\".\n", devname, path);
 
 	return phone;
 }
 
-/** Try to connect to given keyboard, bypassing provided libc routines.
+static int connect_keyboard(const char *path)
+{
+	return connect_keyboard_or_mouse("keyboard", keyboard_events, path);
+}
+
+static int connect_mouse(const char *path)
+{
+	return connect_keyboard_or_mouse("mouse", mouse_events, path);
+}
+
+struct hid_class_info {
+	char *classname;
+	int (*connection_func)(const char *);
+};
+
+/** Periodically check for new keyboards in /dev/class/.
  *
- * @param devmap_path Path to keyboard without /dev prefix.
- * @return Phone or error code.
+ * @param arg Class name.
+ * @return This function should never exit.
  */
-static int connect_keyboard_bypass(char *devmap_path)
-{
-	int devmap_phone = async_connect_me_to_blocking(PHONE_NS,
-	    SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
-	if (devmap_phone < 0) {
-		return devmap_phone;
-	}
-	ipc_call_t answer;
-	aid_t req = async_send_2(devmap_phone, DEVMAP_DEVICE_GET_HANDLE,
-	    0, 0,  &answer);
-
-	sysarg_t retval = async_data_write_start(devmap_phone,
-	    devmap_path, str_size(devmap_path));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_hangup(devmap_phone);
-		return retval;
-	}
-
-	async_wait_for(req, &retval);
-
-	if (retval != EOK) {
-		async_hangup(devmap_phone);
-		return retval;
-	}
-
-	devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(answer);
-
-	async_hangup(devmap_phone);
-
-	int phone = async_connect_me_to(PHONE_NS,
-	    SERVICE_DEVMAP, DEVMAP_CONNECT_TO_DEVICE, handle);
-	if (phone < 0) {
-		return phone;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	sysarg_t phonehash;
-	sysarg_t taskhash;
-	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, SERVICE_CONSOLE,
-	    0, 0, NULL, NULL, NULL, &taskhash, &phonehash);
-	if (rc != EOK) {
-		printf(NAME ": Failed to create callback from input device\n");
-		return rc;
-	}
-
-	async_new_connection(taskhash, phonehash, 0, NULL, keyboard_events);
-
-	printf(NAME ": we got a hit (new keyboard \"/dev/%s\").\n",
-	    devmap_path);
-
-	return phone;
-}
-
-
-static int check_new_keyboards(void *arg)
-{
-	char *class_name = (char *) arg;
-
-	int index = 1;
+static int check_new_device_fibril(void *arg)
+{
+	struct hid_class_info *dev_info = arg;
+
+	size_t index = 1;
 
 	while (true) {
-		async_usleep(1 * 500 * 1000);
+		async_usleep(HOTPLUG_WATCH_INTERVAL);
 		char *path;
-		int rc = asprintf(&path, "class/%s\\%d", class_name, index);
+		int rc = asprintf(&path, "/dev/class/%s\\%zu",
+		    dev_info->classname, index);
 		if (rc < 0) {
 			continue;
 		}
 		rc = 0;
-		rc = connect_keyboard_bypass(path);
+		rc = dev_info->connection_func(path);
 		if (rc > 0) {
 			/* We do not allow unplug. */
@@ -831,9 +792,28 @@
 /** Start a fibril monitoring hot-plugged keyboards.
  */
-static void check_new_keyboards_in_background()
-{
-	fid_t fid = fibril_create(check_new_keyboards, (void *)"keyboard");
+static void check_new_devices_in_background(int (*connection_func)(const char *),
+    const char *classname)
+{
+	struct hid_class_info *dev_info = malloc(sizeof(struct hid_class_info));
+	if (dev_info == NULL) {
+		printf(NAME ": " \
+		    "out of memory, will not start hot-plug-watch fibril.\n");
+		return;
+	}
+	int rc;
+
+	rc = asprintf(&dev_info->classname, "%s", classname);
+	if (rc < 0) {
+		printf(NAME ": failed to format classname: %s.\n",
+		    str_error(rc));
+		return;
+	}
+	dev_info->connection_func = connection_func;
+
+	fid_t fid = fibril_create(check_new_device_fibril, (void *)dev_info);
 	if (!fid) {
-		printf(NAME ": failed to create hot-plug-watch fibril.\n");
+		printf(NAME
+		    ": failed to create hot-plug-watch fibril for %s.\n",
+		    classname);
 		return;
 	}
@@ -849,27 +829,9 @@
 	}
 
-	/* Connect to mouse device */
-	mouse_phone = -1;
-	int mouse_fd = open("/dev/hid_in/mouse", O_RDONLY);
-	
-	if (mouse_fd < 0) {
-		printf(NAME ": Notice - failed opening %s\n", "/dev/hid_in/mouse");
-		goto skip_mouse;
-	}
-	
-	mouse_phone = fd_phone(mouse_fd);
+	mouse_phone = connect_mouse("/dev/hid_in/mouse");
 	if (mouse_phone < 0) {
-		printf(NAME ": Failed to connect to mouse device\n");
-		goto skip_mouse;
-	}
-	
-	if (async_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, mouse_events)
-	    != 0) {
-		printf(NAME ": Failed to create callback from mouse device\n");
-		mouse_phone = -1;
-		goto skip_mouse;
-	}
-	
-skip_mouse:
+		printf(NAME ": Failed to connect to mouse device: %s.\n",
+		    str_error(mouse_phone));
+	}
 	
 	/* Connect to framebuffer driver */
@@ -955,5 +917,6 @@
 	
 	/* Start fibril for checking on hot-plugged keyboards. */
-	check_new_keyboards_in_background();
+	check_new_devices_in_background(connect_keyboard, "keyboard");
+	check_new_devices_in_background(connect_mouse, "mouse");
 
 	return true;
