Index: uspace/lib/usb/include/usb/classes/hiddescriptor.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hiddescriptor.h	(revision 6c6a95d279d3b6dc66db477ee34aa127ededb6c8)
+++ uspace/lib/usb/include/usb/classes/hiddescriptor.h	(revision ba17f5bff553a4de9b48171b4228ed2f86c7481d)
@@ -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 6c6a95d279d3b6dc66db477ee34aa127ededb6c8)
+++ uspace/lib/usb/include/usb/classes/hidpath.h	(revision ba17f5bff553a4de9b48171b4228ed2f86c7481d)
@@ -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 6c6a95d279d3b6dc66db477ee34aa127ededb6c8)
+++ uspace/lib/usb/include/usb/classes/hidtypes.h	(revision ba17f5bff553a4de9b48171b4228ed2f86c7481d)
@@ -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 6c6a95d279d3b6dc66db477ee34aa127ededb6c8)
+++ uspace/lib/usb/src/hiddescriptor.c	(revision ba17f5bff553a4de9b48171b4228ed2f86c7481d)
@@ -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: %X\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: %d\n", report_des->bit_length);		
+		usb_log_debug("\tItems: %d\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 6c6a95d279d3b6dc66db477ee34aa127ededb6c8)
+++ uspace/lib/usb/src/hidparser.c	(revision ba17f5bff553a4de9b48171b4228ed2f86c7481d)
@@ -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 6c6a95d279d3b6dc66db477ee34aa127ededb6c8)
+++ uspace/lib/usb/src/hidpath.c	(revision ba17f5bff553a4de9b48171b4228ed2f86c7481d)
@@ -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;
 
