Index: kernel/generic/include/ddi/irq.h
===================================================================
--- kernel/generic/include/ddi/irq.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ kernel/generic/include/ddi/irq.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -77,5 +77,26 @@
 	 */
 	CMD_PIO_WRITE_A_32,
-	
+
+	/** Read 1 byte from the memory space. */
+	CMD_MEM_READ_8,
+	/** Read 2 bytes from the memory space. */
+	CMD_MEM_READ_16,
+	/** Read 4 bytes from the memory space. */
+	CMD_MEM_READ_32,
+
+	/** Write 1 byte to the memory space. */
+	CMD_MEM_WRITE_8,
+	/** Write 2 bytes to the memory space. */
+	CMD_MEM_WRITE_16,
+	/** Write 4 bytes to the memory space. */
+	CMD_MEM_WRITE_32,
+
+	/** Write 1 byte from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_8,
+	/** Write 2 bytes from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_16,
+	/** Write 4 bytes from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_32,
+
 	/**
 	 * Perform a bit masking on the source argument
@@ -203,4 +224,6 @@
 	/** Notification configuration structure. */
 	ipc_notif_cfg_t notif_cfg; 
+
+	as_t *driver_as;
 } irq_t;
 
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ kernel/generic/src/ipc/irq.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -174,4 +174,5 @@
 	irq->notif_cfg.code = code;
 	irq->notif_cfg.counter = 0;
+	irq->driver_as = AS;
 	
 	/*
@@ -364,4 +365,25 @@
 		return IRQ_DECLINE;
 	
+#define CMD_MEM_READ(target) \
+do { \
+	void *va = code->cmds[i].addr; \
+	if (AS != irq->driver_as) \
+		as_switch(AS, irq->driver_as); \
+	printf("Copying data from address: %p.\n", va); \
+	memcpy_from_uspace(&target, va, (sizeof(target))); \
+	if (dstarg) \
+		scratch[dstarg] = target; \
+} while(0)
+
+#define CMD_MEM_WRITE(val) \
+do { \
+	void *va = code->cmds[i].addr; \
+	if (AS != irq->driver_as) \
+		as_switch(AS, irq->driver_as); \
+	printf("Writing data to address: %p.\n", va); \
+	memcpy_to_uspace(va, &val, sizeof(val)); \
+} while (0)
+
+	as_t *current_as = AS;
 	size_t i;
 	for (i = 0; i < code->cmdcount; i++) {
@@ -422,4 +444,53 @@
 			}
 			break;
+		case CMD_MEM_READ_8: {
+			uint8_t val;
+			CMD_MEM_READ(val);
+			break;
+			}
+		case CMD_MEM_READ_16: {
+			uint16_t val;
+			CMD_MEM_READ(val);
+			break;
+			}
+		case CMD_MEM_READ_32: {
+			uint32_t val;
+			CMD_MEM_READ(val);
+			printf("mem READ value: %x.\n", val);
+			break;
+			}
+		case CMD_MEM_WRITE_8: {
+			uint8_t val = code->cmds[i].value;
+			CMD_MEM_WRITE(val);
+			break;
+			}
+		case CMD_MEM_WRITE_16: {
+			uint16_t val = code->cmds[i].value;
+			CMD_MEM_WRITE(val);
+			break;
+			}
+		case CMD_MEM_WRITE_32: {
+			uint32_t val = code->cmds[i].value;
+			CMD_MEM_WRITE(val);
+			break;
+			}
+		case CMD_MEM_WRITE_A_8:
+			if (srcarg) {
+				uint8_t val = scratch[srcarg];
+				CMD_MEM_WRITE(val);
+			}
+			break;
+		case CMD_MEM_WRITE_A_16:
+			if (srcarg) {
+				uint16_t val = scratch[srcarg];
+				CMD_MEM_WRITE(val);
+			}
+			break;
+		case CMD_MEM_WRITE_A_32:
+			if (srcarg) {
+				uint32_t val = scratch[srcarg];
+				CMD_MEM_WRITE(val);
+			}
+			break;
 		case CMD_BTEST:
 			if ((srcarg) && (dstarg)) {
@@ -435,10 +506,16 @@
 			break;
 		case CMD_ACCEPT:
+			if (AS != current_as)
+				as_switch(AS, current_as);
 			return IRQ_ACCEPT;
 		case CMD_DECLINE:
 		default:
+			if (AS != current_as)
+				as_switch(AS, current_as);
 			return IRQ_DECLINE;
 		}
 	}
+	if (AS != current_as)
+		as_switch(AS, current_as);
 	
 	return IRQ_DECLINE;
Index: uspace/app/netstart/self_test.c
===================================================================
--- uspace/app/netstart/self_test.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
+++ uspace/app/netstart/self_test.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * 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 net
+ * @{
+ */
+
+/** @file
+ * Networking self-tests implementation.
+ *
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+
+#include <net_checksum.h>
+#include <adt/int_map.h>
+#include <adt/char_map.h>
+#include <adt/generic_char_map.h>
+#include <adt/measured_strings.h>
+#include <adt/dynamic_fifo.h>
+
+#include "self_test.h"
+
+/** Test the statement, compare the result and evaluate.
+ *
+ * @param[in] statement The statement to test.
+ * @param[in] result    The expected result.
+ *
+ */
+#define TEST(statement, result) \
+	do { \
+		printf("\n\t%s == %s", #statement, #result); \
+		if ((statement) != (result)) { \
+			printf("\tfailed\n"); \
+			fprintf(stderr, "\nNetwork self-test failed\n"); \
+			return EINVAL; \
+		} else \
+			printf("\tOK"); \
+	} while (0)
+
+#define XMALLOC(var, type) \
+	do { \
+		(var) = (type *) malloc(sizeof(type)); \
+		if ((var) == NULL) { \
+			fprintf(stderr, "\nMemory allocation error\n"); \
+			return ENOMEM; \
+		} \
+	} while (0)
+
+GENERIC_CHAR_MAP_DECLARE(int_char_map, int);
+GENERIC_CHAR_MAP_IMPLEMENT(int_char_map, int);
+
+GENERIC_FIELD_DECLARE(int_field, int);
+GENERIC_FIELD_IMPLEMENT(int_field, int);
+
+INT_MAP_DECLARE(int_map, int);
+INT_MAP_IMPLEMENT(int_map, int);
+
+/** Self-test start function.
+ *
+ * Run all self-tests.
+ *
+ * @returns EOK on success.
+ * @returns The first error occurred.
+ *
+ */
+int self_test(void)
+{
+	printf("Running networking self-tests\n");
+	
+	printf("\nChar map test");
+	char_map_t cm;
+	
+	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
+	TEST(char_map_initialize(&cm), EOK);
+	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_add(&cm, "bla", 0, 1), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 1);
+	TEST(char_map_add(&cm, "bla", 0, 10), EEXISTS);
+	TEST(char_map_update(&cm, "bla", 0, 2), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 2);
+	TEST(char_map_update(&cm, "ucho", 0, 2), EOK);
+	TEST(char_map_exclude(&cm, "bla", 0), 2);
+	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "ucho", 0), 2);
+	TEST(char_map_update(&cm, "ucho", 0, 3), EOK);
+	TEST(char_map_find(&cm, "ucho", 0), 3);
+	TEST(char_map_add(&cm, "blabla", 0, 5), EOK);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "bla", 0, 6), EOK);
+	TEST(char_map_find(&cm, "bla", 0), 6);
+	TEST(char_map_exclude(&cm, "bla", 0), 6);
+	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "auto", 0, 7), EOK);
+	TEST(char_map_find(&cm, "auto", 0), 7);
+	TEST(char_map_add(&cm, "kara", 0, 8), EOK);
+	TEST(char_map_find(&cm, "kara", 0), 8);
+	TEST(char_map_add(&cm, "nic", 0, 9), EOK);
+	TEST(char_map_find(&cm, "nic", 0), 9);
+	TEST(char_map_find(&cm, "blabla", 0), 5);
+	TEST(char_map_add(&cm, "micnicnic", 5, 9), EOK);
+	TEST(char_map_find(&cm, "micni", 0), 9);
+	TEST(char_map_find(&cm, "micnicn", 5), 9);
+	TEST(char_map_add(&cm, "\x10\x0\x2\x2", 4, 15), EOK);
+	TEST(char_map_find(&cm, "\x10\x0\x2\x2", 4), 15);
+	
+	TEST((char_map_destroy(&cm), EOK), EOK);
+	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
+	
+	printf("\nCRC computation test");
+	uint32_t value;
+	
+	TEST(value = ~compute_crc32(~0, "123456789", 8 * 9), 0xcbf43926);
+	TEST(value = ~compute_crc32(~0, "1", 8), 0x83dcefb7);
+	TEST(value = ~compute_crc32(~0, "12", 8 * 2), 0x4f5344cd);
+	TEST(value = ~compute_crc32(~0, "123", 8 * 3), 0x884863d2);
+	TEST(value = ~compute_crc32(~0, "1234", 8 * 4), 0x9be3e0a3);
+	TEST(value = ~compute_crc32(~0, "12345678", 8 * 8), 0x9ae0daaf);
+	TEST(value = ~compute_crc32(~0, "ahoj pane", 8 * 9), 0x5fc3d706);
+	
+	printf("\nDynamic fifo test");
+	dyn_fifo_t fifo;
+	
+	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
+	TEST(dyn_fifo_initialize(&fifo, 1), EOK);
+	TEST(dyn_fifo_push(&fifo, 1, 0), EOK);
+	TEST(dyn_fifo_pop(&fifo), 1);
+	TEST(dyn_fifo_pop(&fifo), ENOENT);
+	TEST(dyn_fifo_push(&fifo, 2, 1), EOK);
+	TEST(dyn_fifo_push(&fifo, 3, 1), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 3, 0), EOK);
+	TEST(dyn_fifo_pop(&fifo), 2);
+	TEST(dyn_fifo_pop(&fifo), 3);
+	TEST(dyn_fifo_push(&fifo, 4, 2), EOK);
+	TEST(dyn_fifo_push(&fifo, 5, 2), EOK);
+	TEST(dyn_fifo_push(&fifo, 6, 2), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 6, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 7, 5), EOK);
+	TEST(dyn_fifo_pop(&fifo), 4);
+	TEST(dyn_fifo_pop(&fifo), 5);
+	TEST(dyn_fifo_push(&fifo, 8, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 9, 5), EOK);
+	TEST(dyn_fifo_push(&fifo, 10, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 11, 6), EOK);
+	TEST(dyn_fifo_pop(&fifo), 6);
+	TEST(dyn_fifo_pop(&fifo), 7);
+	TEST(dyn_fifo_push(&fifo, 12, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 13, 6), EOK);
+	TEST(dyn_fifo_push(&fifo, 14, 6), ENOMEM);
+	TEST(dyn_fifo_push(&fifo, 14, 8), EOK);
+	TEST(dyn_fifo_pop(&fifo), 8);
+	TEST(dyn_fifo_pop(&fifo), 9);
+	TEST(dyn_fifo_pop(&fifo), 10);
+	TEST(dyn_fifo_pop(&fifo), 11);
+	TEST(dyn_fifo_pop(&fifo), 12);
+	TEST(dyn_fifo_pop(&fifo), 13);
+	TEST(dyn_fifo_pop(&fifo), 14);
+	TEST(dyn_fifo_destroy(&fifo), EOK);
+	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
+	
+	printf("\nGeneric char map test");
+	
+	int *x;
+	int *y;
+	int *z;
+	int *u;
+	int *v;
+	int *w;
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_char_map_t icm;
+	icm.magic = 0;
+	
+	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
+	TEST(int_char_map_initialize(&icm), EOK);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), NULL);
+	TEST(int_char_map_add(&icm, "bla", 0, x), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), x);
+	TEST(int_char_map_add(&icm, "bla", 0, y), EEXISTS);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_add(&icm, "blabla", 0, v), EOK);
+	TEST(int_char_map_find(&icm, "blabla", 0), v);
+	TEST(int_char_map_add(&icm, "bla", 0, w), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), w);
+	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
+	TEST(int_char_map_find(&icm, "bla", 0), NULL);
+	TEST(int_char_map_find(&icm, "blabla", 0), v);
+	TEST(int_char_map_add(&icm, "auto", 0, u), EOK);
+	TEST(int_char_map_find(&icm, "auto", 0), u);
+	TEST((int_char_map_destroy(&icm), EOK), EOK);
+	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
+	
+	printf("\nGeneric field test");
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_field_t gf;
+	gf.magic = 0;
+	
+	TEST(int_field_add(&gf, x), EINVAL);
+	TEST(int_field_count(&gf), -1);
+	TEST(int_field_initialize(&gf), EOK);
+	TEST(int_field_count(&gf), 0);
+	TEST(int_field_get_index(&gf, 1), NULL);
+	TEST(int_field_add(&gf, x), 0);
+	TEST(int_field_get_index(&gf, 0), x);
+	TEST((int_field_exclude_index(&gf, 0), EOK), EOK);
+	TEST(int_field_get_index(&gf, 0), NULL);
+	TEST(int_field_add(&gf, y), 1);
+	TEST(int_field_get_index(&gf, 1), y);
+	TEST(int_field_add(&gf, z), 2);
+	TEST(int_field_get_index(&gf, 2), z);
+	TEST(int_field_get_index(&gf, 1), y);
+	TEST(int_field_count(&gf), 3);
+	TEST(int_field_add(&gf, u), 3);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST(int_field_add(&gf, v), 4);
+	TEST(int_field_get_index(&gf, 4), v);
+	TEST(int_field_add(&gf, w), 5);
+	TEST(int_field_get_index(&gf, 5), w);
+	TEST(int_field_count(&gf), 6);
+	TEST((int_field_exclude_index(&gf, 1), EOK), EOK);
+	TEST(int_field_get_index(&gf, 1), NULL);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST((int_field_exclude_index(&gf, 7), EOK), EOK);
+	TEST(int_field_get_index(&gf, 3), u);
+	TEST(int_field_get_index(&gf, 5), w);
+	TEST((int_field_exclude_index(&gf, 4), EOK), EOK);
+	TEST(int_field_get_index(&gf, 4), NULL);
+	TEST((int_field_destroy(&gf), EOK), EOK);
+	TEST(int_field_count(&gf), -1);
+	
+	printf("\nInt map test");
+	
+	XMALLOC(x, int);
+	XMALLOC(y, int);
+	XMALLOC(z, int);
+	XMALLOC(u, int);
+	XMALLOC(v, int);
+	XMALLOC(w, int);
+	
+	int_map_t im;
+	im.magic = 0;
+	
+	TEST(int_map_add(&im, 1, x), EINVAL);
+	TEST(int_map_count(&im), -1);
+	TEST(int_map_initialize(&im), EOK);
+	TEST(int_map_count(&im), 0);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_add(&im, 1, x), 0);
+	TEST(int_map_find(&im, 1), x);
+	TEST((int_map_exclude(&im, 1), EOK), EOK);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_add(&im, 1, y), 1);
+	TEST(int_map_find(&im, 1), y);
+	TEST(int_map_add(&im, 4, z), 2);
+	TEST(int_map_get_index(&im, 2), z);
+	TEST(int_map_find(&im, 4), z);
+	TEST(int_map_find(&im, 1), y);
+	TEST(int_map_count(&im), 3);
+	TEST(int_map_add(&im, 2, u), 3);
+	TEST(int_map_find(&im, 2), u);
+	TEST(int_map_add(&im, 3, v), 4);
+	TEST(int_map_find(&im, 3), v);
+	TEST(int_map_get_index(&im, 4), v);
+	TEST(int_map_add(&im, 6, w), 5);
+	TEST(int_map_find(&im, 6), w);
+	TEST(int_map_count(&im), 6);
+	TEST((int_map_exclude(&im, 1), EOK), EOK);
+	TEST(int_map_find(&im, 1), NULL);
+	TEST(int_map_find(&im, 2), u);
+	TEST((int_map_exclude(&im, 7), EOK), EOK);
+	TEST(int_map_find(&im, 2), u);
+	TEST(int_map_find(&im, 6), w);
+	TEST((int_map_exclude_index(&im, 4), EOK), EOK);
+	TEST(int_map_get_index(&im, 4), NULL);
+	TEST(int_map_find(&im, 3), NULL);
+	TEST((int_map_destroy(&im), EOK), EOK);
+	TEST(int_map_count(&im), -1);
+	
+	printf("\nMeasured strings test");
+	
+	measured_string_ref string =
+	    measured_string_create_bulk("I am a measured string!", 0);
+	printf("\n%x, %s at %x of %d\n", string, string->value, string->value,
+	    string->length);
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/app/netstart/self_test.h
===================================================================
--- uspace/app/netstart/self_test.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
+++ uspace/app/netstart/self_test.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * 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 net
+ * @{
+ */
+
+#ifndef __SELF_TEST_H__
+#define __SELF_TEST_H__
+
+extern int self_test(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/ehci-hcd/ehci-hcd.ma
===================================================================
--- uspace/drv/ehci-hcd/ehci-hcd.ma	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/ehci-hcd/ehci-hcd.ma	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -2,4 +2,5 @@
 10 pci/ven=1002&dev=4386
 10 pci/ven=1002&dev=4396
+10 pci/ven=1002&dev=4373
 10 pci/ven=1022&dev=7463
 10 pci/ven=1022&dev=7808
Index: uspace/drv/ehci-hcd/pci.c
===================================================================
--- uspace/drv/ehci-hcd/pci.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/ehci-hcd/pci.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -186,5 +186,6 @@
 	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read PCI config space.\n",
 	    ret);
-	usb_log_info("Register space BAR at %p:%" PRIxn ".\n", (void *) address, value);
+	usb_log_info("Register space BAR at %p:%" PRIxn ".\n",
+	    (void *) address, value);
 
 	/* clear lower byte, it's not part of the BASE address */
Index: uspace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/ohci/hc.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -45,4 +45,6 @@
 #include "hcd_endpoint.h"
 
+#define OHCI_USED_INTERRUPTS \
+    (I_SO | I_WDH | I_UE | I_RHSC)
 static int interrupt_emulator(hc_t *instance);
 static void hc_gain_control(hc_t *instance);
@@ -285,12 +287,12 @@
 {
 	assert(instance);
-	if ((status & ~IS_SF) == 0) /* ignore sof status */
+	usb_log_debug("OHCI interrupt: %x.\n", status);
+	if ((status & ~I_SF) == 0) /* ignore sof status */
 		return;
-	if (status & IS_RHSC)
+	if (status & I_RHSC)
 		rh_interrupt(&instance->rh);
 
-	usb_log_debug("OHCI interrupt: %x.\n", status);
-
-	if (status & IS_WDH) {
+
+	if (status & I_WDH) {
 		fibril_mutex_lock(&instance->guard);
 		usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
@@ -332,4 +334,5 @@
 {
 	assert(instance);
+	usb_log_debug("Requesting OHCI control.\n");
 	/* Turn off legacy emulation */
 	volatile uint32_t *ohci_emulation_reg =
@@ -337,5 +340,5 @@
 	usb_log_debug("OHCI legacy register %p: %x.\n",
 		ohci_emulation_reg, *ohci_emulation_reg);
-	*ohci_emulation_reg = 0;
+	*ohci_emulation_reg &= ~0x1;
 
 	/* Interrupt routing enabled => smm driver is active */
@@ -421,11 +424,9 @@
 	    instance->registers->control);
 
-	/* Disable interrupts */
-	instance->registers->interrupt_disable = I_SF | I_OC;
-	usb_log_debug2("Disabling interrupts: %x.\n",
-	    instance->registers->interrupt_disable);
-	instance->registers->interrupt_disable = I_MI;
+	/* Enable interrupts */
+	instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;
 	usb_log_debug2("Enabled interrupts: %x.\n",
 	    instance->registers->interrupt_enable);
+	instance->registers->interrupt_enable = I_MI;
 
 	/* Set periodic start to 90% */
@@ -492,4 +493,37 @@
 	    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
 
+	/* Init interrupt code */
+	instance->interrupt_code.cmds = instance->interrupt_commands;
+	{
+		/* Read status register */
+		instance->interrupt_commands[0].cmd = CMD_MEM_READ_32;
+		instance->interrupt_commands[0].dstarg = 1;
+		instance->interrupt_commands[0].addr =
+		    (void*)&instance->registers->interrupt_status;
+
+		/* Test whether we are the interrupt cause */
+		instance->interrupt_commands[1].cmd = CMD_BTEST;
+		instance->interrupt_commands[1].value =
+		    OHCI_USED_INTERRUPTS;
+		instance->interrupt_commands[1].srcarg = 1;
+		instance->interrupt_commands[1].dstarg = 2;
+
+		/* Predicate cleaning and accepting */
+		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
+		instance->interrupt_commands[2].value = 2;
+		instance->interrupt_commands[2].srcarg = 2;
+
+		/* Write clean status register */
+		instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32;
+		instance->interrupt_commands[3].srcarg = 1;
+		instance->interrupt_commands[3].addr =
+		    (void*)&instance->registers->interrupt_status;
+
+		/* Accept interrupt */
+		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
+
+		instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS;
+	}
+
 	return EOK;
 }
Index: uspace/drv/ohci/hc.h
===================================================================
--- uspace/drv/ohci/hc.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/ohci/hc.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -51,4 +51,6 @@
 #include "hw_struct/hcca.h"
 
+#define OHCI_NEEDED_IRQ_COMMANDS 5
+
 typedef struct hc {
 	ohci_regs_t *registers;
@@ -65,4 +67,10 @@
 	fid_t interrupt_emulator;
 	fibril_mutex_t guard;
+
+	/** Code to be executed in kernel interrupt handler */
+	irq_code_t interrupt_code;
+
+	/** Commands that form interrupt code */
+	irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS];
 } hc_t;
 
Index: uspace/drv/ohci/ohci.c
===================================================================
--- uspace/drv/ohci/ohci.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/ohci/ohci.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -202,5 +202,6 @@
 
 	/* It does no harm if we register this on polling */
-	ret = register_interrupt_handler(device, irq, irq_handler, NULL);
+	ret = register_interrupt_handler(device, irq, irq_handler,
+	    &instance->hc.interrupt_code);
 	CHECK_RET_FINI_RETURN(ret,
 	    "Failed(%d) to register interrupt handler.\n", ret);
Index: uspace/drv/ohci/ohci.ma
===================================================================
--- uspace/drv/ohci/ohci.ma	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/ohci/ohci.ma	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -1,3 +1,11 @@
 10 pci/ven=106b&dev=003f
 10 pci/ven=10de&dev=0aa5
-10 pci/ven=10de&dev=0aa5
+
+10 pci/ven=1002&dev=4374
+10 pci/ven=1002&dev=4375
+
+10 pci/ven=1002&dev=4387
+10 pci/ven=1002&dev=4388
+10 pci/ven=1002&dev=4389
+10 pci/ven=1002&dev=438a
+10 pci/ven=1002&dev=438b
Index: uspace/drv/ohci/ohci_regs.h
===================================================================
--- uspace/drv/ohci/ohci_regs.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/ohci/ohci_regs.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -72,16 +72,9 @@
 #define CS_SOC_SHIFT (16)
 
+	/** Interupt enable/disable/status,
+	 * reads give the same value,
+	 * writing causes enable/disable,
+	 * status is write-clean (writing 1 clears the bit*/
 	volatile uint32_t interrupt_status;
-#define IS_SO   (1 << 0)  /* Scheduling overrun */
-#define IS_WDH  (1 << 1)  /* Write-back done head */
-#define IS_SF   (1 << 2)  /* Start of frame */
-#define IS_RD   (1 << 3)  /* Resume detected */
-#define IS_UE   (1 << 4)  /* Unrecoverable error */
-#define IS_FNO  (1 << 5)  /* Frame number overflow */
-#define IS_RHSC (1 << 6)  /* Root hub status change */
-#define IS_OC   (1 << 30) /* Ownership change */
-
-	/** Interupt enable/disable, reads give the same value, writing causes
-	 * enable/disable */
 	volatile uint32_t interrupt_enable;
 	volatile uint32_t interrupt_disable;
Index: uspace/drv/ohci/pci.c
===================================================================
--- uspace/drv/ohci/pci.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/ohci/pci.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -46,23 +46,4 @@
 
 #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.
@@ -146,5 +127,4 @@
 int pci_enable_interrupts(ddf_dev_t *device)
 {
-	return ENOTSUP;
 	int parent_phone =
 	    devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
Index: uspace/drv/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/usbhid/generic/hiddev.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/usbhid/generic/hiddev.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -39,4 +39,5 @@
 #include <errno.h>
 #include <str_error.h>
+#include <bool.h>
 
 #include <usbhid_iface.h>
@@ -64,4 +65,6 @@
     size_t size, size_t *act_size, unsigned int flags);
 
+static int usb_generic_hid_client_connected(ddf_fun_t *fun);
+
 /*----------------------------------------------------------------------------*/
 
@@ -72,5 +75,6 @@
 
 static ddf_dev_ops_t usb_generic_hid_ops = {
-	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface
+	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
+	.open = usb_generic_hid_client_connected
 };
 
@@ -104,10 +108,25 @@
 	
 	/*! @todo This should probably be atomic. */
-	memcpy(buffer, hid_dev->input_report, hid_dev->input_report_size);
-	*act_size = hid_dev->input_report_size;
+	if (usb_hid_report_ready()) {
+		memcpy(buffer, hid_dev->input_report, 
+		    hid_dev->input_report_size);
+		*act_size = hid_dev->input_report_size;
+		usb_hid_report_received();
+	}
 	
 	// clear the buffer so that it will not be received twice
-	memset(hid_dev->input_report, 0, hid_dev->input_report_size);
+	//memset(hid_dev->input_report, 0, hid_dev->input_report_size);
 	
+	// note that we already received this report
+//	report_received = true;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_client_connected(ddf_fun_t *fun)
+{
+	usb_hid_report_received();
 	return EOK;
 }
Index: uspace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/usbhid/kbd/kbddev.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -255,4 +255,6 @@
 	
 	if (hid_dev == NULL || hid_dev->data == NULL) {
+		usb_log_debug("default_connection_handler: "
+		    "Missing parameter.\n");
 		async_answer_0(icallid, EINVAL);
 		return;
@@ -267,4 +269,6 @@
 
 		if (kbd_dev->console_phone != -1) {
+			usb_log_debug("default_connection_handler: "
+			    "console phone already set\n");
 			async_answer_0(icallid, ELIMIT);
 			return;
@@ -272,8 +276,11 @@
 
 		kbd_dev->console_phone = callback;
+		
+		usb_log_debug("default_connection_handler: OK\n");
 		async_answer_0(icallid, EOK);
 		return;
 	}
 	
+	usb_log_debug("default_connection_handler: Wrong function.\n");
 	async_answer_0(icallid, EINVAL);
 }
@@ -555,8 +562,8 @@
 			usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
 			    kbd_dev->keys[i]);
-			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
 			if (!usb_kbd_is_lock(key)) {
 				usb_kbd_repeat_start(kbd_dev, key);
 			}
+			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
 		} else {
 			// found, nothing happens
Index: uspace/drv/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/usbhid/mouse/mousedev.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -43,4 +43,8 @@
 #include <str_error.h>
 #include <ipc/mouse.h>
+#include <io/console.h>
+
+#include <ipc/kbd.h>
+#include <io/keycode.h>
 
 #include "mousedev.h"
@@ -61,5 +65,7 @@
 
 const char *HID_MOUSE_FUN_NAME = "mouse";
+const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
 const char *HID_MOUSE_CLASS_NAME = "mouse";
+const char *HID_MOUSE_WHEEL_CLASS_NAME = "keyboard";
 
 /** Default idle rate for mouses. */
@@ -119,4 +125,6 @@
 	
 	if (hid_dev == NULL || hid_dev->data == NULL) {
+		usb_log_debug("default_connection_handler: Missing "
+		    "parameters.\n");
 		async_answer_0(icallid, EINVAL);
 		return;
@@ -127,13 +135,19 @@
 	usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
 	
+	int *phone = (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) 
+		     ? &mouse_dev->mouse_phone : &mouse_dev->wheel_phone;
+	
 	if (method == IPC_M_CONNECT_TO_ME) {
 		int callback = IPC_GET_ARG5(*icall);
 
-		if (mouse_dev->console_phone != -1) {
+		if (*phone != -1) {
+			usb_log_debug("default_connection_handler: Console "
+			    "phone to mouse already set.\n");
 			async_answer_0(icallid, ELIMIT);
+			//async_answer_0(icallid, EOK);
 			return;
 		}
 
-		mouse_dev->console_phone = callback;
+		*phone = callback;
 		usb_log_debug("Console phone to mouse set ok (%d).\n", callback);
 		async_answer_0(icallid, EOK);
@@ -141,4 +155,5 @@
 	}
 
+	usb_log_debug("default_connection_handler: Invalid function.\n");
 	async_answer_0(icallid, EINVAL);
 }
@@ -152,5 +167,6 @@
 		return NULL;
 	}
-	mouse->console_phone = -1;
+	mouse->mouse_phone = -1;
+	mouse->wheel_phone = -1;
 	
 	return mouse;
@@ -164,6 +180,10 @@
 	
 	// hangup phone to the console
-	if ((*mouse_dev)->console_phone >= 0) {
-		async_hangup((*mouse_dev)->console_phone);
+	if ((*mouse_dev)->mouse_phone >= 0) {
+		async_hangup((*mouse_dev)->mouse_phone);
+	}
+	
+	if ((*mouse_dev)->wheel_phone >= 0) {
+		async_hangup((*mouse_dev)->wheel_phone);
 	}
 	
@@ -174,6 +194,36 @@
 /*----------------------------------------------------------------------------*/
 
-static bool usb_mouse_process_boot_report(usb_hid_dev_t *hid_dev,
-    uint8_t *buffer, size_t buffer_size)
+static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
+{
+	console_event_t ev;
+	
+	ev.type = KEY_PRESS;
+	ev.key = (wheel > 0) ? KC_UP : (wheel < 0) ? KC_DOWN : 0;
+	ev.mods = 0;
+	ev.c = 0;
+
+	if (mouse_dev->wheel_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
+	
+	int count = (wheel < 0) ? -wheel : wheel;
+	int i;
+	
+	for (i = 0; i < count * 3; ++i) {
+		usb_log_debug2("Sending key %d to the console\n", ev.key);
+		async_msg_4(mouse_dev->wheel_phone, KBD_EVENT, ev.type, 
+		    ev.key, ev.mods, ev.c);
+		// send key release right away
+		async_msg_4(mouse_dev->wheel_phone, KBD_EVENT, KEY_RELEASE, 
+		    ev.key, ev.mods, ev.c);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev, uint8_t *buffer,
+    size_t buffer_size)
 {
 	usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
@@ -182,5 +232,5 @@
 	    usb_debug_str_buffer(buffer, buffer_size, 0));
 	
-	if (mouse_dev->console_phone < 0) {
+	if (mouse_dev->mouse_phone < 0) {
 		usb_log_error(NAME " No console phone.\n");
 		return false;	// ??
@@ -252,7 +302,35 @@
 	
 	if ((shift_x != 0) || (shift_y != 0)) {
-		async_req_2_0(mouse_dev->console_phone,
+		async_req_2_0(mouse_dev->mouse_phone,
 		    MEVENT_MOVE, shift_x, shift_y);
 	}
+	
+	/*
+	 * Wheel
+	 */
+	int wheel = 0;
+	
+	path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 
+	    USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
+
+	usb_hid_report_path_set_report_id(path, report_id);
+	
+	field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 
+	    USB_HID_REPORT_TYPE_INPUT);
+
+	if (field != NULL) {
+		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
+		    field->usage);
+		wheel = field->value;
+	}
+
+	usb_hid_report_path_free(path);
+	
+	// send arrow up for positive direction and arrow down for negative
+	// direction; three arrows for difference of 1
+	usb_mouse_send_wheel(mouse_dev, wheel);
+	
 	
 	/*
@@ -274,5 +352,5 @@
 		if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
 		    && field->value != 0) {
-			async_req_2_0(mouse_dev->console_phone,
+			async_req_2_0(mouse_dev->mouse_phone,
 			    MEVENT_BUTTON, field->usage, 1);
 			mouse_dev->buttons[field->usage - field->usage_minimum]
@@ -281,5 +359,5 @@
 		    mouse_dev->buttons[field->usage - field->usage_minimum] != 0
 		    && field->value == 0) {
-		       async_req_2_0(mouse_dev->console_phone,
+		       async_req_2_0(mouse_dev->mouse_phone,
 			   MEVENT_BUTTON, field->usage, 0);
 		       mouse_dev->buttons[field->usage - field->usage_minimum]
@@ -337,4 +415,42 @@
 	}
 	
+	/*
+	 * Special function for acting as keyboard (wheel)
+	 */
+	usb_log_debug("Creating DDF function %s...\n", 
+	              HID_MOUSE_WHEEL_FUN_NAME);
+	fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_MOUSE_WHEEL_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/*
+	 * Store the initialized HID device and HID ops
+	 * to the DDF function.
+	 */
+	fun->ops = &hid_dev->ops;
+	fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("Adding DDF function to class %s...\n", 
+	    HID_MOUSE_WHEEL_CLASS_NAME);
+	rc = ddf_fun_add_to_class(fun, HID_MOUSE_WHEEL_CLASS_NAME);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class %s: %s.\n",
+		    HID_MOUSE_WHEEL_CLASS_NAME, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
 	return EOK;
 }
@@ -407,5 +523,5 @@
 	}
 	
-	return usb_mouse_process_boot_report(hid_dev, buffer, buffer_size);
+	return usb_mouse_process_report(hid_dev, buffer, buffer_size);
 }
 
Index: uspace/drv/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/usbhid/mouse/mousedev.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -48,5 +48,6 @@
 	//suseconds_t poll_interval_us;
 	/** IPC phone to console (consumer). */
-	int console_phone;
+	int mouse_phone;
+	int wheel_phone;
 	
 	int32_t *buttons;
Index: uspace/drv/usbhid/subdrivers.c
===================================================================
--- uspace/drv/usbhid/subdrivers.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/usbhid/subdrivers.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -36,9 +36,16 @@
 #include "subdrivers.h"
 #include "usb/classes/hidut.h"
+#include "usb/classes/hidpath.h"
 
 #include "lgtch-ultrax/lgtch-ultrax.h"
+#include "mouse/mousedev.h"
 
 static usb_hid_subdriver_usage_t path_kbd[] = {
 	{USB_HIDUT_PAGE_KEYBOARD, 0}, 
+	{0, 0}
+};
+
+static usb_hid_subdriver_usage_t path_mouse2[] = {
+	{USB_HIDUT_PAGE_GENERIC_DESKTOP, USB_HIDUT_USAGE_GENERIC_DESKTOP_X},
 	{0, 0}
 };
@@ -79,4 +86,18 @@
 		}
 	},
+	{
+		path_mouse2,
+		-1,
+		USB_HID_PATH_COMPARE_END 
+		| USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+		-1,
+		-1,
+		{
+			.init = usb_mouse_init,
+			.deinit = usb_mouse_deinit,
+			.poll = usb_mouse_polling_callback,
+			.poll_end = NULL
+		}
+	},
 	{NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL}}
 };
Index: uspace/drv/usbhid/usbhid.c
===================================================================
--- uspace/drv/usbhid/usbhid.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/usbhid/usbhid.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -63,4 +63,6 @@
 static const int USB_HID_MAX_SUBDRIVERS = 10;
 
+static fibril_local bool report_received;
+
 /*----------------------------------------------------------------------------*/
 
@@ -412,7 +414,5 @@
 	}
 	
-	// TODO: remove the mouse hack
-	if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO ||
-	    fallback) {
+	if (fallback) {
 		// fall back to boot protocol
 		switch (hid_dev->poll_pipe_index) {
@@ -509,4 +509,5 @@
 				free(input_old);
 			}
+			usb_hid_new_report();
 		}
 	}
@@ -589,4 +590,25 @@
 /*----------------------------------------------------------------------------*/
 
+void usb_hid_new_report(void)
+{
+	report_received = false;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_hid_report_received(void)
+{
+	report_received = true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_hid_report_ready(void)
+{
+	return !report_received;
+}
+
+/*----------------------------------------------------------------------------*/
+
 void usb_hid_free(usb_hid_dev_t **hid_dev)
 {
Index: uspace/drv/usbhid/usbhid.h
===================================================================
--- uspace/drv/usbhid/usbhid.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/drv/usbhid/usbhid.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -44,4 +44,5 @@
 #include <usb/devdrv.h>
 #include <usb/classes/hid.h>
+#include <bool.h>
 
 struct usb_hid_dev;
@@ -128,4 +129,10 @@
 //const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
 
+void usb_hid_new_report(void);
+
+void usb_hid_report_received(void);
+
+bool usb_hid_report_ready(void);
+
 void usb_hid_free(usb_hid_dev_t **hid_dev);
 
Index: pace/lib/packet/include/net_byteorder.h
===================================================================
--- uspace/lib/packet/include/net_byteorder.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ 	(revision )
@@ -1,71 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 net
- *  @{
- */
-
-/** @file
- *  Host - network byte order manipulation functions.
- */
-
-#ifndef __NET_BYTEORDER_H__
-#define __NET_BYTEORDER_H__
-
-#include <byteorder.h>
-#include <sys/types.h>
-
-
-/** Converts the given short number (16 bit) from the host byte order to the network byte order (big endian).
- *  @param[in] number The number in the host byte order to be converted.
- *  @returns The number in the network byte order.
- */
-#define htons(number)		host2uint16_t_be(number)
-
-/** Converts the given long number (32 bit) from the host byte order to the network byte order (big endian).
- *  @param[in] number The number in the host byte order to be converted.
- *  @returns The number in the network byte order.
- */
-#define htonl(number)		host2uint32_t_be(number)
-
-/** Converts the given short number (16 bit) from the network byte order (big endian) to the host byte order.
- *  @param[in] number The number in the network byte order to be converted.
- *  @returns The number in the host byte order.
- */
-#define ntohs(number) 	uint16_t_be2host(number)
-
-/** Converts the given long number (32 bit) from the network byte order (big endian) to the host byte order.
- *  @param[in] number The number in the network byte order to be converted.
- *  @returns The number in the host byte order.
- */
-#define ntohl(number)		uint32_t_be2host(number)
-
-#endif
-
-/** @}
- */
Index: pace/lib/packet/include/net_err.h
===================================================================
--- uspace/lib/packet/include/net_err.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ 	(revision )
@@ -1,99 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 net
- * @{
- */
-
-/** @file
- * Common error processing codes and routines.
- */
-
-#ifndef __NET_ERR_H__
-#define __NET_ERR_H__
-
-#include <errno.h>
-
-#ifdef CONFIG_DEBUG
-	#include <stdio.h>
-	#include <str_error.h>
-#endif
-
-/** An actual stored error code.
- *
- */
-#define ERROR_CODE  error_check_return_value
-
-/** An error processing routines declaration.
- *
- * This has to be declared in the block where the error processing
- * is desired.
- *
- */
-#define ERROR_DECLARE  int ERROR_CODE
-
-/** Store the value as an error code and checks if an error occurred.
- *
- * @param[in] value The value to be checked. May be a function call.
- * @return False if the value indicates success (EOK).
- * @return True otherwise.
- *
- */
-#ifdef CONFIG_DEBUG
-
-#define ERROR_OCCURRED(value) \
-	(((ERROR_CODE = (value)) != EOK) \
-	&& ({ \
-		fprintf(stderr, "libsocket error at %s:%d (%s)\n", \
-		__FILE__, __LINE__, str_error(ERROR_CODE)); \
-		1; \
-	}))
-
-#else
-
-#define ERROR_OCCURRED(value)  ((ERROR_CODE = (value)) != EOK)
-
-#endif
-
-/** Error propagation
- *
- * Check if an error occurred and immediately exit the actual
- * function returning the error code.
- *
- * @param[in] value The value to be checked. May be a function call.
- *
- */
-
-#define ERROR_PROPAGATE(value) \
-	if (ERROR_OCCURRED(value)) \
-		return ERROR_CODE
-
-#endif
-
-/** @}
- */
Index: pace/lib/packet/include/socket_errno.h
===================================================================
--- uspace/lib/packet/include/socket_errno.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ 	(revision )
@@ -1,136 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * 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 net
- *  @{
- */
-
-/** @file
- *  Socket error codes.
- *  Based on BSD.
- */
-
-#ifndef __NET_SOCKET_ERR_H__
-#define __NET_SOCKET_ERR_H__
-
-#include <errno.h>
-
-/** @name Socket error codes definitions
- */
-/*@{*/
-
-////#define EINTR			(-10004)
-////#define EBADF			(-10009)
-//#define EACCES			(-10013)
-//#define EFAULT			(-10014)
-////#define EINVAL			(-10022)
-////#define EMFILE			(-10024)
-//#define EWOULDBLOCK		(-10035)
-
-/** An API function is called while another blocking function is in progress.
- */
-#define EINPROGRESS		(-10036)
-
-//#define EALREADY		(-10037)
-
-/** The socket identifier is not valid.
- */
-#define ENOTSOCK		(-10038)
-
-/** The destination address required.
- */
-#define EDESTADDRREQ	(-10039)
-
-//#define EMSGSIZE		(-10040)
-//#define EPROTOTYPE		(-10041)
-//#define ENOPROTOOPT		(-10042)
-
-/** Protocol is not supported.
- */
-#define EPROTONOSUPPORT	(-10043)
-
-/** Socket type is not supported.
- */
-#define ESOCKTNOSUPPORT	(-10044)
-
-//#define EOPNOTSUPP		(-10045)
-
-/** Protocol family is not supported.
- */
-#define EPFNOSUPPORT	(-10046)
-
-/** Address family is not supported.
- */
-#define EAFNOSUPPORT	(-10047)
-
-/** Address is already in use.
- */
-#define EADDRINUSE		(-10048)
-
-//#define EADDRNOTAVAIL	(-10049)
-/* May be reported at any time if the implementation detects an underlying failure.
- */
-//#define ENETDOWN		(-10050)
-//#define ENETUNREACH		(-10051)
-//#define ENETRESET		(-10052)
-//#define ECONNABORTED	(-10053)
-//#define ECONNRESET		(-10054)
-//#define ENOBUFS			(-10055)
-//#define EISCONN			(-10056)
-
-/** The socket is not connected or bound.
- */
-#define ENOTCONN		(-10057)
-
-//#define ESHUTDOWN		(-10058)
-//#define ETOOMANYREFS	(-10059)
-//#define ETIMEDOUT		(-10060)
-//#define ECONNREFUSED	(-10061)
-//#define ELOOP			(-10062)
-////#define ENAMETOOLONG	(-10063)
-//#define EHOSTDOWN		(-10064)
-//#define EHOSTUNREACH	(-10065)
-//#define HOST_NOT_FOUND	(-11001)
-
-/** The requested operation was not performed.
- *  Try again later.
- */
-#define TRY_AGAIN		(-11002)
-
-//#define NO_RECOVERY		(-11003)
-
-/** No data.
- */
-#define NO_DATA			(-11004)
-
-/*@}*/
-
-#endif
-
-/** @}
- */
Index: uspace/lib/usb/include/usb/classes/hiddescriptor.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hiddescriptor.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/lib/usb/include/usb/classes/hiddescriptor.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -78,4 +78,5 @@
 uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
 
+usb_hid_report_path_t *usb_hid_report_path_try_insert(usb_hid_report_t *report, usb_hid_report_path_t *cmp_path);
 #endif
 /**
Index: uspace/lib/usb/include/usb/classes/hidpath.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidpath.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/lib/usb/include/usb/classes/hidpath.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -43,8 +43,14 @@
  * Description of path of usage pages and usages in report descriptor
  */
-#define USB_HID_PATH_COMPARE_STRICT				0
-#define USB_HID_PATH_COMPARE_END				1
-#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY	4
-#define USB_HID_PATH_COMPARE_COLLECTION_ONLY	2 /* porovnava jenom cestu z Kolekci */
+/** Wanted usage path must be exactly the same as the searched one */
+#define USB_HID_PATH_COMPARE_STRICT		0
+/** Wanted usage path must be the suffix in the searched one */
+#define USB_HID_PATH_COMPARE_END		1
+/** */
+#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY	2
+/** Searched usage page must be prefix of the other one */
+#define USB_HID_PATH_COMPARE_BEGIN		4
+/** Searched couple of usage page and usage can be anywhere in usage path */
+#define USB_HID_PATH_COMPARE_ANYWHERE		8
 
 
Index: uspace/lib/usb/include/usb/classes/hidtypes.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidtypes.h	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/lib/usb/include/usb/classes/hidtypes.h	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -165,4 +165,6 @@
 	/** */	
 	link_t link;
+
+	int in_delimiter;
 } usb_hid_report_item_t;
 
Index: uspace/lib/usb/src/hiddescriptor.c
===================================================================
--- uspace/lib/usb/src/hiddescriptor.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/lib/usb/src/hiddescriptor.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -41,4 +41,9 @@
 #include <assert.h>
 
+
+#define OUTSIDE_DELIMITER_SET	0
+#define START_DELIMITER_SET	1
+#define INSIDE_DELIMITER_SET	2
+	
 /** The new report item flag. Used to determine when the item is completly
  * configured and should be added to the report structure
@@ -56,31 +61,6 @@
 #define USB_HID_UNKNOWN_TAG		-99
 
-
-/**
- * Initialize the report descriptor parser structure
- *
- * @param parser Report descriptor parser structure
- * @return Error code
- */
-int usb_hid_report_init(usb_hid_report_t *report)
-{
-	if(report == NULL) {
-		return EINVAL;
-	}
-
-	memset(report, 0, sizeof(usb_hid_report_t));
-	list_initialize(&report->reports);
-	list_initialize(&report->collection_paths);
-
-	report->use_report_ids = 0;
-    return EOK;   
-}
-
-int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
-{
-	usb_hid_report_field_t *field;
-	int i;
-
-
+usb_hid_report_path_t *usb_hid_report_path_try_insert(usb_hid_report_t *report, usb_hid_report_path_t *cmp_path)
+{
 	/* find or append current collection path to the list */
 	link_t *path_it = report->collection_paths.next;
@@ -89,5 +69,5 @@
 		path = list_get_instance(path_it, usb_hid_report_path_t, link);
 		
-		if(usb_hid_report_compare_usage_path(path, report_item->usage_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
+		if(usb_hid_report_compare_usage_path(path, cmp_path, USB_HID_PATH_COMPARE_STRICT) == EOK){
 			break;
 		}			
@@ -95,8 +75,44 @@
 	}
 	if(path_it == &report->collection_paths) {
-		path = usb_hid_report_path_clone(report_item->usage_path);			
+		path = usb_hid_report_path_clone(cmp_path);			
 		list_append(&path->link, &report->collection_paths);					
 		report->collection_paths_count++;
-	}
+
+		return path;
+	}
+	else {
+		return list_get_instance(path_it, usb_hid_report_path_t, link);
+	}
+}
+
+/**
+ * Initialize the report descriptor parser structure
+ *
+ * @param parser Report descriptor parser structure
+ * @return Error code
+ */
+int usb_hid_report_init(usb_hid_report_t *report)
+{
+	if(report == NULL) {
+		return EINVAL;
+	}
+
+	memset(report, 0, sizeof(usb_hid_report_t));
+	list_initialize(&report->reports);
+	list_initialize(&report->collection_paths);
+
+	report->use_report_ids = 0;
+    return EOK;   
+}
+
+
+/*
+ *
+ *
+ */
+int usb_hid_report_append_fields(usb_hid_report_t *report, usb_hid_report_item_t *report_item)
+{
+	usb_hid_report_field_t *field;
+	int i;
 
 	for(i=0; i<report_item->usages_count; i++){
@@ -104,5 +120,5 @@
 	}
 
-	
+	usb_hid_report_path_t *path = report_item->usage_path;	
 	for(i=0; i<report_item->count; i++){
 
@@ -112,5 +128,4 @@
 
 		/* fill the attributes */		
-		field->collection_path = path;
 		field->logical_minimum = report_item->logical_minimum;
 		field->logical_maximum = report_item->logical_maximum;
@@ -129,19 +144,9 @@
 		if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
 			uint32_t usage;
-			if(report_item->type != USB_HID_REPORT_TYPE_OUTPUT) {
-				if(i < report_item->usages_count){
-					usage = report_item->usages[i];
-				}
-				else {
-					usage = report_item->usages[report_item->usages_count - 1];
-				}
+			if(i < report_item->usages_count){
+				usage = report_item->usages[i];
 			}
 			else {
-				if((report_item->count - i - 1) < report_item->usages_count){
-					usage = report_item->usages[(report_item->count - i - 1)];
-				}
-				else {
-					usage = report_item->usages[report_item->usages_count - 1];
-				}
+				usage = report_item->usages[report_item->usages_count - 1];
 			}
 
@@ -159,15 +164,18 @@
 
 		if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) != 0) && (!((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0)))) {
-			if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
-				field->usage = report_item->usage_maximum - i;
-			}
-			else {
-				field->usage = report_item->usage_minimum + i;					
-			}
-
-		}
-		
+			field->usage = report_item->usage_minimum + i;					
+		}
+		
+		usb_hid_report_set_last_item(path, USB_HID_TAG_CLASS_GLOBAL, field->usage_page);
+		usb_hid_report_set_last_item(path, USB_HID_TAG_CLASS_LOCAL, field->usage);
+
+		field->collection_path = usb_hid_report_path_try_insert(report, path);
+
 		field->size = report_item->size;
-		field->offset = report_item->offset + (i * report_item->size);
+		
+		size_t offset_byte = (report_item->offset + (i * report_item->size)) / 8;
+		size_t offset_bit = 8 - ((report_item->offset + (i * report_item->size)) % 8) - report_item->size;
+
+		field->offset = 8 * offset_byte + offset_bit;
 		if(report_item->id != 0) {
 			field->offset += 8;
@@ -264,4 +272,5 @@
 		return ENOMEM;
 	}
+	usb_hid_report_path_append_item(usage_path, 0, 0);	
 	
 	while(i<size){	
@@ -349,5 +358,6 @@
 					tmp_usage_path = list_get_instance(report_item->usage_path->link.prev, usb_hid_report_usage_path_t, link);
 					
-					usb_hid_report_set_last_item(usage_path, tmp_usage_path->usage_page, tmp_usage_path->usage);
+					usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL, tmp_usage_path->usage_page);
+					usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL, tmp_usage_path->usage);
 
 					usb_hid_report_path_free(report_item->usage_path);
@@ -427,5 +437,7 @@
 int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, size_t item_size,
                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
-{		
+{
+	usb_hid_report_usage_path_t *path_item;
+	
 	switch(tag)
 	{
@@ -438,6 +450,15 @@
 			
 		case USB_HID_REPORT_TAG_COLLECTION:
-			// TODO usage_path->flags = *data;
-			usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);						
+			// store collection atributes
+			path_item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
+			path_item->flags = *data;	
+			
+			// set last item
+			usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL, report_item->usage_page);
+			usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL, report_item->usages[report_item->usages_count-1]);
+			
+			// append the new one which will be set by common
+			// usage/usage page
+			usb_hid_report_path_append_item(usage_path, report_item->usage_page, report_item->usages[report_item->usages_count-1]);	
 			usb_hid_report_reset_local_items (report_item);
 			return USB_HID_NO_ACTION;
@@ -530,9 +551,17 @@
                              usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
 {
-	switch(tag)
-	{
+	switch(tag) {
 		case USB_HID_REPORT_TAG_USAGE:
-			report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
-			report_item->usages_count++;
+			switch(report_item->in_delimiter) {
+				case INSIDE_DELIMITER_SET:
+					// nothing to do
+					break;
+				case START_DELIMITER_SET:
+					report_item->in_delimiter = INSIDE_DELIMITER_SET;
+				case OUTSIDE_DELIMITER_SET:
+					report_item->usages[report_item->usages_count] = usb_hid_report_tag_data_uint32(data,item_size);
+					report_item->usages_count++;
+					break;
+			}
 			break;
 		case USB_HID_REPORT_TAG_USAGE_MINIMUM:
@@ -575,13 +604,11 @@
 			break;			
 		case USB_HID_REPORT_TAG_DELIMITER:
-			//report_item->delimiter = usb_hid_report_tag_data_uint32(data,item_size);
-			//TODO: 
-			//	DELIMITER STUFF
-			break;
-		
+			report_item->in_delimiter = usb_hid_report_tag_data_uint32(data,item_size);
+			break;
+
 		default:
 			return USB_HID_NO_ACTION;
 	}
-	
+
 	return EOK;
 }
@@ -629,5 +656,5 @@
 
 		usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
-		usb_log_debug("\t\tSIZE: %zu\n", report_item->size);
+		usb_log_debug("\t\tSIZE: %zu\n", report_item->size);				
 		usb_log_debug("\t\tLOGMIN: %d\n", report_item->logical_minimum);
 		usb_log_debug("\t\tLOGMAX: %d\n", report_item->logical_maximum);		
@@ -640,6 +667,8 @@
 		usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
 		usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
-						
-//		usb_log_debug("\n");		
+		
+		//usb_hid_print_usage_path(report_item->collection_path);
+
+		usb_log_debug("\n");		
 
 	}
@@ -666,6 +695,6 @@
 		usb_log_debug("Report ID: %d\n", report_des->report_id);
 		usb_log_debug("\tType: %d\n", report_des->type);
-		usb_log_debug("\tLength: %zu\n", report_des->bit_length);
-		usb_log_debug("\tItems: %zu\n", report_des->item_length);
+		usb_log_debug("\tLength: %zu\n", report_des->bit_length);		
+		usb_log_debug("\tItems: %zu\n", report_des->item_length);		
 
 		usb_hid_descriptor_print_list(&report_des->report_items);
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/lib/usb/src/hidparser.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -405,5 +405,5 @@
 				}
 
-				size_t shift = offset%8;
+				size_t shift = 8 - offset%8 - length;
 
 				value = value << shift;							
Index: uspace/lib/usb/src/hidpath.c
===================================================================
--- uspace/lib/usb/src/hidpath.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/lib/usb/src/hidpath.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -149,5 +149,5 @@
 		usb_log_debug("\tFLAGS: %d\n", path_item->flags);		
 		
-		item = item->next;
+       		item = item->next;
 	}
 }
@@ -156,7 +156,6 @@
  * Compares two usage paths structures
  *
- * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten
- *
- * @param report_path usage path structure to compare
+ *
+ * @param report_path usage path structure to compare with @path 
  * @param path usage patrh structure to compare
  * @param flags Flags determining the mode of comparison
@@ -179,4 +178,5 @@
 	}
 
+	// Empty path match all others
 	if(path->depth == 0){
 		return EOK;
@@ -189,10 +189,43 @@
 	
 	switch(flags){
-		/* path must be completly identical */
+		/* path is somewhere in report_path */
+		case USB_HID_PATH_COMPARE_ANYWHERE:
+			if(path->depth != 1){
+				return 1;
+			}
+
+			// projit skrz cestu a kdyz nekde sedi tak vratim EOK
+			// dojduli az za konec tak nnesedi
+			report_link = report_path->head.next;
+			path_link = path->head.next;
+			path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
+
+			while(report_link != &report_path->head) {
+				report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
+				if(report_item->usage_page == path_item->usage_page){
+					if(only_page == 0){
+						if(report_item->usage == path_item->usage) {
+							return EOK;
+						}
+					}
+					else {
+						return EOK;
+					}
+				}
+
+				report_link = report_link->next;
+			}
+
+			return 1;
+			break;
+		/* the paths must be identical */
 		case USB_HID_PATH_COMPARE_STRICT:
 				if(report_path->depth != path->depth){
 					return 1;
 				}
-
+		
+		/* path is prefix of the report_path */
+		case USB_HID_PATH_COMPARE_BEGIN:
+	
 				report_link = report_path->head.next;
 				path_link = path->head.next;
@@ -221,8 +254,6 @@
 				}
 
-				if(((report_link == &report_path->head) && (path_link == &path->head)) || 
-				   (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) && 
-				    (path_link = &path->head) && 
-				    (report_link == report_path->head.prev))) {
+				if((((flags & USB_HID_PATH_COMPARE_BEGIN) != 0) && (path_link == &path->head)) || 
+				   ((report_link == &report_path->head) && (path_link == &path->head))) {
 					return EOK;
 				}
@@ -232,13 +263,8 @@
 			break;
 
-		/* compare with only the end of path*/
+		/* path is suffix of report_path */
 		case USB_HID_PATH_COMPARE_END:
 
-				if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) {
-					report_link = report_path->head.prev->prev;
-				}
-				else {
-					report_link = report_path->head.prev;
-				}
+				report_link = report_path->head.prev;
 				path_link = path->head.prev;
 
Index: uspace/lib/usb/src/host/batch.c
===================================================================
--- uspace/lib/usb/src/host/batch.c	(revision beee81a7687467f9672b71143423415145ae7160)
+++ uspace/lib/usb/src/host/batch.c	(revision bc02b831ff3b4c4e8b3650696bf99682e93453af)
@@ -128,9 +128,10 @@
 	memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
 
-	usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
+	usb_log_debug("Batch(%p) done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
 	    instance, instance->ep->address, instance->ep->endpoint,
 	    usb_str_speed(instance->ep->speed),
 	    usb_str_transfer_type_short(instance->ep->transfer_type),
-	    instance->transfered_size, str_error(instance->error), instance->error);
+	    instance->transfered_size, str_error(instance->error),
+	    instance->error);
 
 	instance->callback_in(instance->fun, instance->error,
@@ -147,5 +148,5 @@
 	assert(instance->callback_out);
 
-	usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n",
+	usb_log_debug("Batch(%p) done (T%d.%d, %s %s out): %s (%d).\n",
 	    instance, instance->ep->address, instance->ep->endpoint,
 	    usb_str_speed(instance->ep->speed),
