Index: uspace/drv/usbhid/hiddev.c
===================================================================
--- uspace/drv/usbhid/hiddev.c	(revision 4f66cc7ba6fe619d454d7dc98d744ace7725d190)
+++ uspace/drv/usbhid/hiddev.c	(revision 6e3b9a58b081735910fd5e1021d0427056ca9eb3)
@@ -158,4 +158,6 @@
 	}
 	
+	hid_dev->report_desc_size = length;
+	
 	usb_log_debug("Done.\n");
 	
@@ -262,8 +264,18 @@
 	
 	if (rc != EOK) {
-		usb_log_warning("Problem with parsing Report descriptor: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
+		usb_log_warning("Problem with getting Report descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	rc = usb_hid_parse_report_descriptor(hid_dev->parser, 
+	    hid_dev->report_desc, hid_dev->report_desc_size);
+	if (rc != EOK) {
+		usb_log_warning("Problem parsing Report descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_hid_descriptor_print(hid_dev->parser);
 	
 	return EOK;
@@ -289,4 +301,12 @@
 	
 	memset(dev, 0, sizeof(usbhid_dev_t));
+	
+	dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
+	    usb_hid_report_parser_t)));
+	if (dev->parser == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(dev);
+		return NULL;
+	}
 	
 	dev->initialized = 0;
@@ -399,4 +419,13 @@
 
 	/*
+	 * Initialize the report parser.
+	 */
+	rc = usb_hid_parser_init(hid_dev->parser);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize report parser.\n");
+		return rc;
+	}
+
+	/*
 	 * Get descriptors, parse descriptors and save endpoints.
 	 */
Index: uspace/drv/usbhid/hiddev.h
===================================================================
--- uspace/drv/usbhid/hiddev.h	(revision 4f66cc7ba6fe619d454d7dc98d744ace7725d190)
+++ uspace/drv/usbhid/hiddev.h	(revision 6e3b9a58b081735910fd5e1021d0427056ca9eb3)
@@ -75,4 +75,7 @@
 	/** Report descriptor. */
 	uint8_t *report_desc;
+
+	size_t report_desc_size;
+
 	/** HID Report parser. */
 	usb_hid_report_parser_t *parser;
Index: uspace/drv/usbhid/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbddev.c	(revision 4f66cc7ba6fe619d454d7dc98d744ace7725d190)
+++ uspace/drv/usbhid/kbddev.c	(revision 6e3b9a58b081735910fd5e1021d0427056ca9eb3)
@@ -502,5 +502,5 @@
 
 	usb_log_debug("Got keys from parser: %s\n", 
-	    usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0));
+	    usb_debug_str_buffer(key_codes, count, 0));
 	
 	if (count != kbd_dev->key_count) {
@@ -535,4 +535,7 @@
                                     uint8_t *buffer, size_t actual_size)
 {
+	assert(kbd_dev->initialized);
+	assert(kbd_dev->hid_dev->parser != NULL);
+	
 	usb_hid_report_in_callbacks_t *callbacks =
 	    (usb_hid_report_in_callbacks_t *)malloc(
@@ -541,9 +544,11 @@
 	callbacks->keyboard = usbhid_kbd_process_keycodes;
 
-	usb_log_debug("Calling usb_hid_boot_keyboard_input_report() with "
+	usb_log_debug("Calling usb_hid_parse_report() with "
 	    "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0));
 	
-	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
-	    callbacks, kbd_dev);
+//	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
+//	    callbacks, kbd_dev);
+	int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer,
+	    actual_size, callbacks, kbd_dev);
 	
 	if (rc != EOK) {
@@ -614,5 +619,5 @@
 		free((*kbd_dev)->repeat_mtx);
 	}
-	
+
 	free(*kbd_dev);
 	*kbd_dev = NULL;
@@ -709,5 +714,5 @@
 	assert(kbd_dev->hid_dev != NULL);
 	assert(kbd_dev->hid_dev->initialized);
-	usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
+	//usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
 	
 	usbhid_kbd_set_led(kbd_dev);
Index: uspace/drv/usbhid/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbddev.h	(revision 4f66cc7ba6fe619d454d7dc98d744ace7725d190)
+++ uspace/drv/usbhid/kbddev.h	(revision 6e3b9a58b081735910fd5e1021d0427056ca9eb3)
@@ -42,4 +42,5 @@
 
 #include <usb/classes/hid.h>
+#include <usb/classes/hidparser.h>
 #include <ddf/driver.h>
 #include <usb/pipes.h>
Index: uspace/lib/usb/include/usb/classes/hid_report_items.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hid_report_items.h	(revision 6e3b9a58b081735910fd5e1021d0427056ca9eb3)
+++ uspace/lib/usb/include/usb/classes/hid_report_items.h	(revision 6e3b9a58b081735910fd5e1021d0427056ca9eb3)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb
+ * @{
+ */
+/** @file
+ * @brief USB HID parser.
+ */
+#ifndef LIBUSB_HID_REPORT_ITEMS_H_
+#define LIBUSB_HID_REPORT_ITEMS_H_
+
+#include <stdint.h>
+
+/* MAIN ITEMS */
+#define USB_HID_TAG_CLASS_MAIN				0x0
+#define USB_HID_REPORT_TAG_INPUT			0x8
+#define USB_HID_REPORT_TAG_OUTPUT			0x9
+#define USB_HID_REPORT_TAG_FEATURE			0xB
+#define USB_HID_REPORT_TAG_COLLECTION		0xA
+#define USB_HID_REPORT_TAG_END_COLLECTION	0xC
+
+/* GLOBAL ITEMS */
+#define USB_HID_TAG_CLASS_GLOBAL			0x1
+#define USB_HID_REPORT_TAG_USAGE_PAGE		0x0
+#define USB_HID_REPORT_TAG_LOGICAL_MINIMUM	0x1
+#define USB_HID_REPORT_TAG_LOGICAL_MAXIMUM	0x2
+#define USB_HID_REPORT_TAG_PHYSICAL_MINIMUM 0x3
+#define USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM 0x4
+#define USB_HID_REPORT_TAG_UNIT_EXPONENT	0x5
+#define USB_HID_REPORT_TAG_UNIT				0x6
+#define USB_HID_REPORT_TAG_REPORT_SIZE		0x7
+#define USB_HID_REPORT_TAG_REPORT_ID		0x8
+#define USB_HID_REPORT_TAG_REPORT_COUNT		0x9
+#define USB_HID_REPORT_TAG_PUSH				0xA
+#define USB_HID_REPORT_TAG_POP				0xB
+
+
+/* LOCAL ITEMS */
+#define USB_HID_TAG_CLASS_LOCAL					0x2
+#define USB_HID_REPORT_TAG_USAGE				0x0
+#define USB_HID_REPORT_TAG_USAGE_MINIMUM		0x1
+#define USB_HID_REPORT_TAG_USAGE_MAXIMUM		0x2
+#define USB_HID_REPORT_TAG_DESIGNATOR_INDEX		0x3
+#define USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM	0x4
+#define USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM	0x5
+#define USB_HID_REPORT_TAG_STRING_INDEX			0x7
+#define USB_HID_REPORT_TAG_STRING_MINIMUM		0x8
+#define USB_HID_REPORT_TAG_STRING_MAXIMUM		0x9
+#define USB_HID_REPORT_TAG_DELIMITER			0xA
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/classes/hidparser.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidparser.h	(revision 4f66cc7ba6fe619d454d7dc98d744ace7725d190)
+++ uspace/lib/usb/include/usb/classes/hidparser.h	(revision 6e3b9a58b081735910fd5e1021d0427056ca9eb3)
@@ -37,4 +37,29 @@
 
 #include <stdint.h>
+#include <adt/list.h>
+#include <usb/classes/hid_report_items.h>
+
+/**
+ * Item 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)
+
 
 /**
@@ -42,19 +67,44 @@
  */
 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;
+	size_t offset;
+	int32_t delimiter;
 
-	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;	
+
 
 
@@ -127,4 +177,5 @@
 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);
@@ -135,5 +186,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 4f66cc7ba6fe619d454d7dc98d744ace7725d190)
+++ uspace/lib/usb/src/hidparser.c	(revision 6e3b9a58b081735910fd5e1021d0427056ca9eb3)
@@ -36,4 +36,62 @@
 #include <errno.h>
 #include <stdio.h>
+#include <malloc.h>
+#include <mem.h>
+#include <usb/debug.h>
+
+#define USB_HID_NEW_REPORT_ITEM 1
+#define USB_HID_NO_ACTION		2
+#define USB_HID_UNKNOWN_TAG		-99
+
+#define BAD_HACK_USAGE_PAGE		0x07
+
+int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item);
+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);
+int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item);
+int usb_hid_report_parse_local_tag(uint8_t tag, const 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 *head);
+int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size);
+inline size_t usb_hid_count_item_offset(usb_hid_report_item_t * report_item, size_t offset);
+int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j);
+int usb_pow(int a, int b);
+
+int usb_pow(int a, int b)
+{
+	switch(b) {
+		case 0:
+			return 1;
+			break;
+		case 1:
+			return a;
+			break;
+		default:
+			return a * usb_pow(a, b-1);
+			break;
+	}
+}
+
+/**
+ *
+ */
+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));
+
+    return EOK;   
+}
+
 
 /** Parse HID report descriptor.
@@ -46,5 +104,478 @@
     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;
+
+	size_t offset_input=0;
+	size_t offset_output=0;
+	size_t offset_feature=0;
+	
+
+	if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
+		return ENOMEM;
+	}
+	memset(report_item, 0, sizeof(usb_hid_report_item_t));
+	
+	link_initialize(&(report_item->link));	
+
+	while(i<size){	
+		if(!USB_HID_ITEM_IS_LONG(data[i])){
+
+			if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
+				return -1; // TODO ERROR CODE
+			}
+			
+			tag = USB_HID_ITEM_TAG(data[i]);
+			item_size = USB_HID_ITEM_SIZE(data[i]);
+			class = USB_HID_ITEM_TAG_CLASS(data[i]);
+
+			usb_log_debug2(
+				"i(%u) data(%X) value(%X): TAG %u, class %u, size %u - ", i, 
+			    data[i], usb_hid_report_tag_data_int32(data+i+1,item_size), 
+			    tag, class, item_size);
+			
+			ret = usb_hid_report_parse_tag(tag,class,data+i+1,
+			                         item_size,report_item);
+			usb_log_debug2("ret: %u\n", ret);
+			switch(ret){
+				case USB_HID_NEW_REPORT_ITEM:
+					// store report item to report and create the new one
+					usb_log_debug("\nNEW REPORT ITEM: %X",tag);
+					
+					switch(tag) {
+						case USB_HID_REPORT_TAG_INPUT:
+							report_item->offset = offset_input;
+							offset_input += report_item->count * report_item->size;
+							usb_log_debug(" - INPUT\n");
+							list_append(&(report_item->link), &(parser->input));
+							break;
+						case USB_HID_REPORT_TAG_OUTPUT:
+							report_item->offset = offset_output;
+							offset_output += report_item->count * report_item->size;
+							usb_log_debug(" - OUTPUT\n");
+								list_append(&(report_item->link), &(parser->output));
+
+							break;
+						case USB_HID_REPORT_TAG_FEATURE:
+							report_item->offset = offset_feature;
+							offset_feature += report_item->count * report_item->size;
+							usb_log_debug(" - FEATURE\n");
+								list_append(&(report_item->link), &(parser->feature));
+							break;
+						default:
+						    usb_log_debug("\tjump over - tag %X\n", tag);
+						    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;
+}
+
+
+/**
+ * Parse input report.
+ *
+ * @param data Data for report
+ * @param size Size of report
+ * @param callbacks Callbacks for report actions
+ * @param arg Custom arguments
+ *
+ * @return Error code
+ */
+int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
+	const usb_hid_report_in_callbacks_t *callbacks, void *arg)
+{
+	int i;
+	usb_hid_report_item_t item;
+
+	/* fill item due to the boot protocol report descriptor */
+	// modifier keys are in the first byte
+	uint8_t modifiers = data[0];
+
+	item.offset = 2; /* second byte is reserved */
+	item.size = 8;
+	item.count = 6;
+	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 = 0; i < item.count; i++) {
+		keys[i] = data[i + item.offset];
+	}
+
+	callbacks->keyboard(keys, 6, modifiers, arg);
+	return EOK;
+}
+
+/**
+ * Makes output report for keyboard boot protocol
+ *
+ * @param leds
+ * @param output Output report data buffer
+ * @param size Size of the output buffer
+ * @return Error code
+ */
+int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
+{
+	if(size != 1){
+		return -1;
+	}
+
+	/* used only first five bits, others are only padding*/
+	*data = leds;
+	return EOK;
+}
+
+/**
+ *
+ * @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, const uint8_t *data, size_t item_size,
+                             usb_hid_report_item_t *report_item)
+{	
+	int ret;
+	
+	switch(class){
+		case USB_HID_TAG_CLASS_MAIN:
+
+			if((ret=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 ret;
+			   }
+			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 USB_HID_NO_ACTION;
+	}
+}
+
+/**
+ * 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, const 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 EOK;			
+			break;
+			
+		case USB_HID_REPORT_TAG_COLLECTION:
+			// TODO
+			return USB_HID_NO_ACTION;
+			break;
+			
+		case USB_HID_REPORT_TAG_END_COLLECTION:
+			/* should be ignored */
+			return USB_HID_NO_ACTION;
+			break;
+		default:
+			return USB_HID_NO_ACTION;
+	}
+
+	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, const 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 USB_HID_NO_ACTION;
+	}
+	
+	return EOK;
+}
+
+/**
+ * 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, const 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 USB_HID_NO_ACTION;
+	}
+	
+	return EOK;
+}
+
+/**
+ * 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(const uint8_t *data, size_t size)
+{
+	unsigned 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)) {
+	    usb_log_debug("\tempty\n");
+	    return;
+	}
+        
+	for(item = head->next; item != head; item = item->next) {
+                
+		report_item = list_get_instance(item, usb_hid_report_item_t, link);
+
+		usb_log_debug("\tOFFSET: %X\n", report_item->offset);
+		usb_log_debug("\tCOUNT: %X\n", report_item->count);
+		usb_log_debug("\tSIZE: %X\n", report_item->size);
+		usb_log_debug("\tCONSTANT: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
+		usb_log_debug("\tUSAGE: %X\n", report_item->usage);
+		usb_log_debug("\tUSAGE PAGE: %X\n", report_item->usage_page);
+		usb_log_debug("\tLOGMIN: %X\n", report_item->logical_minimum);
+		usb_log_debug("\tLOGMAX: %X\n", report_item->logical_maximum);		
+		usb_log_debug("\tPHYMIN: %X\n", report_item->physical_minimum);		
+		usb_log_debug("\tPHYMAX: %X\n", report_item->physical_maximum);				
+		usb_log_debug("\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)
+{
+	usb_log_debug("INPUT:\n");
+	usb_hid_descriptor_print_list(&parser->input);
+	
+	usb_log_debug("OUTPUT: \n");
+	usb_hid_descriptor_print_list(&parser->output);
+	
+	usb_log_debug("FEATURE:\n");	
+	usb_hid_descriptor_print_list(&parser->feature);
+
+}
+
+/**
+ * Releases whole linked list of report items
+ *
+ * 
+ */
+void usb_hid_free_report_list(link_t *head)
+{
+	return; 
+	
+	usb_hid_report_item_t *report_item;
+	link_t *next;
+	
+	if(head == NULL || list_empty(head)) {		
+	    return;
+	}
+	
+	next = head->next;
+	while(next != head) {
+	
+	    report_item = list_get_instance(next, usb_hid_report_item_t, link);
+	    next = next->next;
+	    
+	    free(report_item);
+	}
+	
+	return;
+	
+}
+
+/** Free the HID report parser structure 
+ *
+ * @param parser Opaque HID report parser structure
+ * @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;
 }
 
@@ -58,98 +589,134 @@
  * @param arg Custom argument (passed through to the callbacks).
  * @return Error code.
- */
+ */ 
 int usb_hid_parse_report(const usb_hid_report_parser_t *parser,  
     const uint8_t *data, size_t size,
     const usb_hid_report_in_callbacks_t *callbacks, void *arg)
 {
-	int i;
-	
-	/* main parsing loop */
-	while(0){
-	}
-	
-	
-	uint8_t keys[6];
-	
-	for (i = 0; i < 6; ++i) {
-		keys[i] = data[i];
-	}
-	
-	callbacks->keyboard(keys, 6, 0, arg);
-
+	/*
+	 *
+	 * only key codes (usage page 0x07) will be processed
+	 * other usages will be ignored 
+	 */
+	link_t *list_item;
+	usb_hid_report_item_t *item;
+	uint8_t *keys;
+	size_t key_count=0;
+	size_t i=0;
+	size_t j=0;
+
+	// get the size of result keycodes array
+	list_item = parser->input.next;	   
+	while(list_item != &(parser->input)) {
+
+		item = list_get_instance(list_item, usb_hid_report_item_t, link);
+		if(item->usage_page == BAD_HACK_USAGE_PAGE) {
+			key_count += item->count;
+		}
+
+		list_item = list_item->next;
+	}
+
+	
+	if(!(keys = malloc(sizeof(uint8_t) * key_count))){
+		return ENOMEM;
+	}
+
+	// read data		
+	list_item = parser->input.next;	   
+	while(list_item != &(parser->input)) {
+
+		item = list_get_instance(list_item, usb_hid_report_item_t, link);
+		if(item->usage_page == BAD_HACK_USAGE_PAGE) {
+			for(j=0; j<(size_t)(item->count); j++) {
+				keys[i++] = usb_hid_translate_data(item, data,j);
+			}
+		}
+		list_item = list_item->next;
+	}
+
+	callbacks->keyboard(keys, key_count, 0, arg);
+	   
+	free(keys);	
 	return EOK;
-}
-
-/** Free the HID report parser structure 
- *
- * @param parser Opaque HID report parser structure
- * @return Error code
- */
-int usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
-{
-
-	return EOK;
-}
-
-
-/**
- * Parse input report.
- *
- * @param data Data for report
- * @param size Size of report
- * @param callbacks Callbacks for report actions
- * @param arg Custom arguments
- *
- * @return Error code
- */
-int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
-	const usb_hid_report_in_callbacks_t *callbacks, void *arg)
-{
-	int i;
-	usb_hid_report_item_t item;
-
-	/* fill item due to the boot protocol report descriptor */
-	// modifier keys are in the first byte
-	uint8_t modifiers = data[0];
-
-	item.offset = 2; /* second byte is reserved */
-	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 ERANGE;
-	}
-
-	uint8_t keys[6];
-	for (i = 0; i < item.count; i++) {
-		keys[i] = data[i + item.offset];
-	}
-
-	callbacks->keyboard(keys, 6, modifiers, arg);
-	return EOK;
-}
-
-/**
- * Makes output report for keyboard boot protocol
- *
- * @param leds
- * @param output Output report data buffer
- * @param size Size of the output buffer
- * @return Error code
- */
-int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size)
-{
-	if (size < 1){
-		return -1;
-	}
-
-	data[0] = leds;
-	return EOK;
-}
-
+	
+}
+
+
+int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
+{
+	int resolution;
+	int offset;
+	int part_size;
+	
+	int32_t value;
+	int32_t mask;
+	const uint8_t *foo;
+	
+	// now only common numbers llowed
+	if(item->size > 32) {
+		return 0;
+	}
+
+	if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
+		item->physical_minimum = item->logical_minimum;
+		item->physical_maximum = item->logical_maximum;		
+	}
+
+	if(item->physical_maximum == item->physical_minimum){
+	    resolution = 1;
+	}
+	else {
+	    resolution = (item->logical_maximum - item->logical_minimum) / 
+		((item->physical_maximum - item->physical_minimum) * 
+		(usb_pow(10,(item->unit_exponent))));
+	}
+	offset = item->offset + (j * item->size);
+	
+	// FIXME
+	if((offset/8) != ((offset+item->size)/8)) {
+		usb_log_debug2("offset %d\n", offset);
+		
+		part_size = ((offset+item->size)%8);
+		usb_log_debug2("part size %d\n",part_size);
+
+		// the higher one
+		foo = data+(offset/8);
+		mask =  ((1 << (item->size-part_size))-1);
+		value = (*foo & mask) << part_size;
+
+		usb_log_debug2("hfoo %x\n", *foo);
+		usb_log_debug2("hmaska %x\n",  mask);
+		usb_log_debug2("hval %d\n", value);		
+
+		// the lower one
+		foo = data+((offset+item->size)/8);
+		mask =  ((1 << part_size)-1) << (8-part_size);
+		value += ((*foo & mask) >> (8-part_size));
+
+		usb_log_debug2("lfoo %x\n", *foo);
+		usb_log_debug2("lmaska %x\n",  mask);
+		usb_log_debug2("lval %d\n", ((*foo & mask) >> (8-(item->size-part_size))));		
+		usb_log_debug2("val %d\n", value);
+		
+		
+	}
+	else {		
+		foo = data+(offset/8);
+		mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
+		value = (*foo & mask) >> (8-((offset%8)+item->size));
+
+		usb_log_debug2("offset %d\n", offset);
+	
+		usb_log_debug2("foo %x\n", *foo);
+		usb_log_debug2("maska %x\n",  mask);
+		usb_log_debug2("val %d\n", value);				
+	}
+
+	usb_log_debug2("---\n\n"); 
+
+	return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
+	
+}
 /**
  * @}
