Index: uspace/lib/usb/include/usb/classes/hidparser.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidparser.h	(revision 2f60e57de62931ac2568d3cc4757af6a827a6565)
+++ uspace/lib/usb/include/usb/classes/hidparser.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -37,4 +37,50 @@
 
 #include <stdint.h>
+#include <adt/list.h>
+
+#include <hid_report_items.h>
+
+/**
+ * Items prefix
+ */
+#define USB_HID_ITEM_SIZE(data) 	((uint8_t)(data & 0x3))
+#define USB_HID_ITEM_TAG(data) 		((uint8_t)((data & 0xF0) >> 4))
+#define USB_HID_ITEM_TAG_CLASS(data)	((uint8_t)((data & 0xC) >> 2))
+#define USB_HID_ITEM_IS_LONG(data)	(data == 0xFE)
+
+
+/**
+ * Input/Output/Feature Item flags
+ */
+#define USB_HID_ITEM_FLAG_CONSTANT(flags) 	(flags & 0x1)
+#define USB_HID_ITEM_FLAG_VARIABLE(flags) 	(flags & 0x2)
+#define USB_HID_ITEM_FLAG_RELATIVE(flags) 	(flags & 0x4)
+#define USB_HID_ITEM_FLAG_WRAP(flags)		(flags & 0x8)
+#define USB_HID_ITEM_FLAG_LINEAR(flags)		(flags & 0x10)
+#define USB_HID_ITEM_FLAG_PREFERRED(flags)	(flags & 0x20)
+#define USB_HID_ITEM_FLAG_POSITION(flags)	(flags & 0x40)
+#define USB_HID_ITEM_FLAG_VOLATILE(flags)	(flags & 0x80)
+#define USB_HID_ITEM_FLAG_BUFFERED(flags)	(flags & 0x100)
+
+
+/**
+ * Collection Item Types
+ */
+#define USB_HID_COLLECTION_TYPE_PHYSICAL		0x00
+#define USB_HID_COLLECTION_TYPE_APPLICATION		0x01
+#define USB_HID_COLLECTION_TYPE_LOGICAL			0x02
+#define USB_HID_COLLECTION_TYPE_REPORT			0x03
+#define USB_HID_COLLECTION_TYPE_NAMED_ARRAY		0x04
+#define USB_HID_COLLECTION_TYPE_USAGE_SWITCH	0x05
+
+/*
+ * modifiers definitions
+ */
+#define USB_HID_BOOT_KEYBOARD_NUM_LOCK		0x01
+#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK		0x02
+#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK	0x04
+#define USB_HID_BOOT_KEYBOARD_COMPOSE		0x08
+#define USB_HID_BOOT_KEYBOARD_KANA			0x10
+
 
 /**
@@ -42,19 +88,42 @@
  */
 typedef struct {
+	int32_t id;
+	int32_t usage_page;
+	int32_t	usage;	
+	int32_t usage_minimum;
+	int32_t usage_maximum;
+	int32_t logical_minimum;
+	int32_t logical_maximum;
+	int32_t size;
+	int32_t count;
+	int32_t offset;
 
-	uint8_t usage_min;
-	uint8_t usage_max;
-	uint8_t logical_min;
-	uint8_t logical_max;
-	uint8_t size;
-	uint8_t count;
-	uint8_t offset;
+	int32_t unit_exponent;
+	int32_t unit;
 
+	/*
+	 * some not yet used fields
+	 */
+	int32_t string_index;
+	int32_t string_minimum;
+	int32_t string_maximum;
+	int32_t designator_index;
+	int32_t designator_minimum;
+	int32_t designator_maximum;
+	int32_t physical_minimum;
+	int32_t physical_maximum;
+
+	uint8_t item_flags;
+
+	link_t link;
 } usb_hid_report_item_t;
 
 
 /** HID report parser structure. */
-typedef struct {
-} usb_hid_report_parser_t;
+typedef struct {	
+	link_t input;
+	link_t output;
+	link_t feature;
+} usb_hid_report_parser_t;	
 
 
@@ -70,14 +139,4 @@
 } usb_hid_report_in_callbacks_t;
 
-#define USB_HID_BOOT_KEYBOARD_NUM_LOCK		0x01
-#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK		0x02
-#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK	0x04
-#define USB_HID_BOOT_KEYBOARD_COMPOSE		0x08
-#define USB_HID_BOOT_KEYBOARD_KANA			0x10
-
-/*
- * modifiers definitions
- */
-
 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
 	const usb_hid_report_in_callbacks_t *callbacks, void *arg);
@@ -85,4 +144,6 @@
 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
 
+
+int usb_hid_parser_init(usb_hid_report_parser_t *parser);
 int usb_hid_parse_report_descriptor(usb_hid_report_parser_t *parser, 
     const uint8_t *data, size_t size);
@@ -93,6 +154,7 @@
 
 
-int usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
+void usb_hid_free_report_parser(usb_hid_report_parser_t *parser);
 
+void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
 #endif
 /**
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision 2f60e57de62931ac2568d3cc4757af6a827a6565)
+++ uspace/lib/usb/src/hidparser.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -35,4 +35,38 @@
 #include <usb/classes/hidparser.h>
 #include <errno.h>
+#include <stdio.h>
+#include <adt/list.h>
+
+#define USB_HID_NEW_REPORT_ITEM 0
+
+
+int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item);
+int usb_hid_report_parse_main_tag(uint8_t tag, uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item);
+int usb_hid_report_parse_global_tag(uint8_t tag, uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item);
+int usb_hid_report_parse_local_tag(uint8_t tag, uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item);
+
+void usb_hid_descriptor_print_list(link_t *head)
+int usb_hid_report_reset_local_items();
+void usb_hid_free_report_list(link_t *list);
+
+/**
+ *
+ */
+int usb_hid_parser_init(usb_hid_report_parser_t *parser)
+{
+   if(parser == NULL) {
+	return -1;
+   }
+
+    list_initialize(&(parser->input));
+    list_initialize(&(parser->output));
+    list_initialize(&(parser->feature));
+   
+}
+
 
 /** Parse HID report descriptor.
@@ -45,5 +79,87 @@
     const uint8_t *data, size_t size)
 {
-	return ENOTSUP;
+	size_t i=0;
+	uint8_t tag=0;
+	uint8_t item_size=0;
+	int class=0;
+	int ret;
+	usb_hid_report_item_t *report_item=0;
+	usb_hid_report_item_t *new_report_item;
+	
+
+	if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
+		return ENOMEM;
+	}
+	link_initialize(&(report_item->link));	
+	
+	while(i<size){
+		
+		if(!USB_HID_ITEM_IS_LONG(data[i])){
+			tag = USB_HID_ITEM_TAG(data[i]);
+			item_size = USB_HID_ITEM_SIZE(data[i]);
+			class = USB_HID_ITEM_TAG_CLASS(data[i]);
+						
+			ret = usb_hid_report_parse_tag(tag,class,
+			                         (uint8_t *)(data + sizeof(uint8_t)*(i+1)),
+			                         item_size,report_item);
+			switch(ret){
+				case USB_HID_NEW_REPORT_ITEM:
+					// store report item to report and create the new one
+					printf("\nNEW REPORT ITEM: %X",tag);
+					switch(tag) {
+						case USB_HID_REPORT_TAG_INPUT:
+							printf(" - INPUT\n");
+							list_append(&(report_item->link), &(parser->input));
+							break;
+						case USB_HID_REPORT_TAG_OUTPUT:
+							printf(" - OUTPUT\n");
+								list_append(&(report_item->link), &(parser->output));
+
+							break;
+						case USB_HID_REPORT_TAG_FEATURE:
+							printf(" - FEATURE\n");
+								list_append(&(report_item->link), &(parser->feature));
+							break;
+						default:
+						    printf("\tjump over\n");
+						    break;
+					}
+
+					/* clone current state table to the new item */
+					if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
+						return ENOMEM;
+					}
+					memcpy(new_report_item,report_item, sizeof(usb_hid_report_item_t));
+					link_initialize(&(new_report_item->link));
+					report_item = new_report_item;
+					
+					break;
+				case USB_HID_REPORT_TAG_PUSH:
+					// push current state to stack
+					// not yet implemented
+					break;
+				case USB_HID_REPORT_TAG_POP:
+					// restore current state from stack
+					// not yet implemented						   
+					break;
+					
+				default:
+					// nothing special to do
+					break;
+			}
+
+			/* jump over the processed block */
+			i += 1 + USB_HID_ITEM_SIZE(data[i]);
+		}
+		else{
+			// TBD
+			i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
+		}
+		
+
+	}
+	
+
+	return EOK;
 }
 
@@ -115,16 +231,16 @@
 	item.size = 8;
 	item.count = 6;
-	item.usage_min = 0;
-	item.usage_max = 255;
-	item.logical_min = 0;
-	item.logical_max = 255;
-
-	if(size != 8){
-		return -1;
+	item.usage_minimum = 0;
+	item.usage_maximum = 255;
+	item.logical_minimum = 0;
+	item.logical_maximum = 255;
+
+	if (size != 8) {
+		return -1;//ERANGE;
 	}
 
 	uint8_t keys[6];
-	for(i=item.offset; i<item.count; i++) {
-		keys[i-2] = data[i];
+	for (i = 0; i < item.count; i++) {
+		keys[i] = data[i + item.offset];
 	}
 
@@ -153,4 +269,299 @@
 
 /**
+ *
+ * @param Tag to parse
+ * @param Report descriptor buffer
+ * @param Size of data belongs to this tag
+ * @param Current report item structe
+ * @return Code of action to be done next
+ */
+int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item)
+{	
+	switch(class){
+		case USB_HID_TAG_CLASS_MAIN:
+
+			if(usb_hid_report_parse_main_tag(tag,data,item_size,report_item) == EOK) {
+				return USB_HID_NEW_REPORT_ITEM;
+			}
+			else {
+				/*TODO process the error */
+				return -1;
+			   }
+			break;
+
+		case USB_HID_TAG_CLASS_GLOBAL:	
+			return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
+			break;
+
+		case USB_HID_TAG_CLASS_LOCAL:			
+			return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
+			break;
+		default:
+			return -1; /* TODO ERROR CODE - UNKNOWN TAG CODE */
+	}
+}
+
+/**
+ * Parse main tags of report descriptor
+ *
+ * @param Tag identifier
+ * @param Data buffer
+ * @param Length of data buffer
+ * @param Current state table
+ * @return Error code
+ */
+
+int usb_hid_report_parse_main_tag(uint8_t tag, uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item)
+{
+	switch(tag)
+	{
+		case USB_HID_REPORT_TAG_INPUT:
+		case USB_HID_REPORT_TAG_OUTPUT:
+		case USB_HID_REPORT_TAG_FEATURE:
+			report_item->item_flags = *data;
+			return USB_HID_NEW_REPORT_ITEM;
+			break;
+			
+		case USB_HID_REPORT_TAG_COLLECTION:
+			// TODO
+			break;
+			
+		case USB_HID_REPORT_TAG_END_COLLECTION:
+			/* should be ignored */
+			break;
+		default:
+			return -1; //TODO ERROR CODE
+	}
+
+	return EOK;
+}
+
+/**
+ * Parse global tags of report descriptor
+ *
+ * @param Tag identifier
+ * @param Data buffer
+ * @param Length of data buffer
+ * @param Current state table
+ * @return Error code
+ */
+
+int usb_hid_report_parse_global_tag(uint8_t tag, uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item)
+{
+	// TODO take care about the bit length of data
+	switch(tag)
+	{
+		case USB_HID_REPORT_TAG_USAGE_PAGE:
+			report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
+			report_item->logical_minimum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
+			report_item->logical_maximum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
+			report_item->physical_minimum = usb_hid_report_tag_data_int32(data,item_size);
+			break;			
+		case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
+			report_item->physical_maximum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_UNIT_EXPONENT:
+			report_item->unit_exponent = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_UNIT:
+			report_item->unit = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_REPORT_SIZE:
+			report_item->size = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_REPORT_COUNT:
+			report_item->count = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_REPORT_ID:
+			report_item->id = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_PUSH:
+		case USB_HID_REPORT_TAG_POP:
+			return tag;
+			break;
+			
+		default:
+			return -1; //TODO ERROR CODE INVALID GLOBAL TAG
+	}
+}
+
+/**
+ * Parse local tags of report descriptor
+ *
+ * @param Tag identifier
+ * @param Data buffer
+ * @param Length of data buffer
+ * @param Current state table
+ * @return Error code
+ */
+int usb_hid_report_parse_local_tag(uint8_t tag, uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item)
+{
+	switch(tag)
+	{
+		case USB_HID_REPORT_TAG_USAGE:
+			report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_USAGE_MINIMUM:
+			report_item->usage_minimum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
+			report_item->usage_maximum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
+			report_item->designator_index = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
+			report_item->designator_minimum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
+			report_item->designator_maximum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_STRING_INDEX:
+			report_item->string_index = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_STRING_MINIMUM:
+			report_item->string_minimum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_STRING_MAXIMUM:
+			report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		case USB_HID_REPORT_TAG_DELIMITER:
+			report_item->delimiter = usb_hid_report_tag_data_int32(data,item_size);
+			break;
+		
+		default:
+			return -1; //TODO ERROR CODE INVALID LOCAL TAG NOW IS ONLY UNSUPPORTED
+	}
+}
+
+/**
+ * Converts raw data to int32 (thats the maximum length of short item data)
+ *
+ * @param Data buffer
+ * @param Size of buffer
+ * @return Converted int32 number
+ */
+int32_t usb_hid_report_tag_data_int32(uint8_t *data, size_t size)
+{
+	int i;
+	int32_t result;
+
+	result = 0;
+	for(i=0; i<size; i++) {
+		result = (result | (data[i]) << (i*8));
+	}
+
+	return result;
+}
+
+
+
+/**
+ * Prints content of given list of report items.
+ *
+ * @param List of report items
+ * @return void
+ */
+void usb_hid_descriptor_print_list(link_t *head)
+{
+	usb_hid_report_item_t *report_item;
+	link_t *item;
+	
+	if(head == NULL || list_empty(head)) {
+	    printf("\tempty\n");
+	    return;
+	}
+
+	
+        printf("\tHEAD %p\n",head);
+	for(item = head->next; item != head; item = item->next) {
+                
+		report_item = list_get_instance(item, usb_hid_report_item_t, link);
+
+		printf("\tOFFSET: %X\n", report_item->offset);
+		printf("\tCOUNT: %X\n", report_item->count);
+		printf("\tSIZE: %X\n", report_item->size);
+		printf("\tCONSTANT: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
+		printf("\tUSAGE: %X\n", report_item->usage);
+		printf("\tUSAGE PAGE: %X\n", report_item->usage_page);
+		printf("\n");		
+
+	}
+
+
+}
+/**
+ * Prints content of given descriptor in human readable format.
+ *
+ * @param Parsed descriptor to print
+ * @return void
+ */
+void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
+{
+	printf("INPUT:\n");
+	usb_hid_descriptor_print_list(&parser->input);
+	
+	printf("OUTPUT: \n");
+	usb_hid_descriptor_print_list(&parser->output);
+	
+	printf("FEATURE:\n");	
+	usb_hid_descriptor_print_list(&parser->feature);
+
+}
+
+/**
+ * Releases whole linked list of report items
+ *
+ * 
+ */
+void usb_hid_free_report_list(link_t *list)
+{
+	usb_hid_report_item_t *report_item;
+	link_t *item;
+	
+	if(head == NULL || list_empty(head)) {		
+	    return EOK;
+	}
+	    
+	for(item = head->next; item != head; item = item->next) {
+		list_remove(item);
+		free(list_get_instance(item,usb_hid_report_item_t, link));
+	}
+}
+
+/**
+ * Frees complete structure of report parser
+ * 
+ * @param Parser to free
+ * @return Error code
+ */
+void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
+{
+	if(parser == NULL){
+		return;
+	}
+
+	usb_hid_free_report_list(&parser->input);
+	usb_hid_free_report_list(&parser->output);
+	usb_hid_free_report_list(&parser->feature);
+
+	return;
+}
+/**
  * @}
  */
+
+
+/**
+ * @}
+ */
