Index: uspace/lib/usb/include/usb/classes/hid_report_items.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hid_report_items.h	(revision 8e9becf6f03c7ac046d50d671c046eae94548328)
+++ uspace/lib/usb/include/usb/classes/hid_report_items.h	(revision 021351c49ad9b282c9fd4387a343e613e66462f4)
@@ -42,6 +42,6 @@
 #define USB_HID_REPORT_TAG_INPUT			0x8
 #define USB_HID_REPORT_TAG_OUTPUT			0x9
-#define USB_HID_REPORT_TAG_FEATURE			0xA
-#define USB_HID_REPORT_TAG_COLLECTION		0xB
+#define USB_HID_REPORT_TAG_FEATURE			0xB
+#define USB_HID_REPORT_TAG_COLLECTION		0xA
 #define USB_HID_REPORT_TAG_END_COLLECTION	0xC
 
Index: uspace/lib/usb/include/usb/classes/hidparser.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidparser.h	(revision 8e9becf6f03c7ac046d50d671c046eae94548328)
+++ uspace/lib/usb/include/usb/classes/hidparser.h	(revision 021351c49ad9b282c9fd4387a343e613e66462f4)
@@ -76,5 +76,6 @@
 	int32_t size;
 	int32_t count;
-	int32_t offset;
+	size_t offset;
+	int32_t delimiter;
 
 	int32_t unit_exponent;
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision 8e9becf6f03c7ac046d50d671c046eae94548328)
+++ uspace/lib/usb/src/hidparser.c	(revision 021351c49ad9b282c9fd4387a343e613e66462f4)
@@ -36,18 +36,21 @@
 #include <errno.h>
 #include <stdio.h>
-#include <adt/list.h>
 #include <malloc.h>
 #include <mem.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,
+#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, uint8_t *data, size_t item_size,
+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, uint8_t *data, size_t item_size,
+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, uint8_t *data, size_t item_size,
+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);
 
@@ -55,5 +58,24 @@
 int usb_hid_report_reset_local_items();
 void usb_hid_free_report_list(link_t *head);
-int32_t usb_hid_report_tag_data_int32(uint8_t *data, size_t size);
+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;
+	}
+}
+
 /**
  *
@@ -89,4 +111,6 @@
 	usb_hid_report_item_t *report_item=0;
 	usb_hid_report_item_t *new_report_item;
+
+	size_t offset=0;
 	
 
@@ -95,35 +119,48 @@
 	}
 	link_initialize(&(report_item->link));	
-	
-	while(i<size){
-		
+
+	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]);
-						
-			ret = usb_hid_report_parse_tag(tag,class,
-			                         (uint8_t *)(data + sizeof(uint8_t)*(i+1)),
+
+			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
-					printf("\nNEW REPORT ITEM: %X",tag);
+					usb_log_debug("\nNEW REPORT ITEM: %X",tag);
+
+					report_item->offset = offset;
+					offset += report_item->count * report_item->size;
+					
 					switch(tag) {
 						case USB_HID_REPORT_TAG_INPUT:
-							printf(" - INPUT\n");
+							usb_log_debug(" - INPUT\n");
 							list_append(&(report_item->link), &(parser->input));
 							break;
 						case USB_HID_REPORT_TAG_OUTPUT:
-							printf(" - OUTPUT\n");
+							usb_log_debug(" - OUTPUT\n");
 								list_append(&(report_item->link), &(parser->output));
 
 							break;
 						case USB_HID_REPORT_TAG_FEATURE:
-							printf(" - FEATURE\n");
+							usb_log_debug(" - FEATURE\n");
 								list_append(&(report_item->link), &(parser->feature));
 							break;
 						default:
-						    printf("\tjump over\n");
+						    usb_log_debug("\tjump over - tag %X\n", tag);
 						    break;
 					}
@@ -148,5 +185,5 @@
 					
 				default:
-					// nothing special to do
+					// nothing special to do					
 					break;
 			}
@@ -163,37 +200,4 @@
 	}
 	
-
-	return EOK;
-}
-
-/** Parse and act upon a HID report.
- *
- * @see usb_hid_parse_report_descriptor
- *
- * @param parser Opaque HID report parser structure.
- * @param data Data for the report.
- * @param callbacks Callbacks for report actions.
- * @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);
-
 	return EOK;
 }
@@ -268,16 +272,18 @@
  * @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,
+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(usb_hid_report_parse_main_tag(tag,data,item_size,report_item) == EOK) {
+			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 -1;
+				return ret;
 			   }
 			break;
@@ -291,5 +297,5 @@
 			break;
 		default:
-			return -1; /* TODO ERROR CODE - UNKNOWN TAG CODE */
+			return USB_HID_NO_ACTION;
 	}
 }
@@ -305,5 +311,5 @@
  */
 
-int usb_hid_report_parse_main_tag(uint8_t tag, uint8_t *data, size_t item_size,
+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)
 {
@@ -313,17 +319,19 @@
 		case USB_HID_REPORT_TAG_OUTPUT:
 		case USB_HID_REPORT_TAG_FEATURE:
-			report_item->item_flags = *data;
-			return USB_HID_NEW_REPORT_ITEM;
+			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 -1; //TODO ERROR CODE
+			return USB_HID_NO_ACTION;
 	}
 
@@ -341,5 +349,5 @@
  */
 
-int usb_hid_report_parse_global_tag(uint8_t tag, uint8_t *data, size_t item_size,
+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)
 {
@@ -383,5 +391,5 @@
 			
 		default:
-			return -1; //TODO ERROR CODE INVALID GLOBAL TAG
+			return USB_HID_NO_ACTION;
 	}
 	
@@ -398,5 +406,5 @@
  * @return Error code
  */
-int usb_hid_report_parse_local_tag(uint8_t tag, uint8_t *data, size_t item_size,
+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)
 {
@@ -429,12 +437,11 @@
 		case USB_HID_REPORT_TAG_STRING_MAXIMUM:
 			report_item->string_maximum = usb_hid_report_tag_data_int32(data,item_size);
-			break;
-/*			
+			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
+			return USB_HID_NO_ACTION;
 	}
 	
@@ -449,5 +456,5 @@
  * @return Converted int32 number
  */
-int32_t usb_hid_report_tag_data_int32(uint8_t *data, size_t size)
+int32_t usb_hid_report_tag_data_int32(const uint8_t *data, size_t size)
 {
 	unsigned int i;
@@ -479,7 +486,5 @@
 	    return;
 	}
-
-	
-        printf("\tHEAD %p\n",head);
+        
 	for(item = head->next; item != head; item = item->next) {
                 
@@ -492,4 +497,8 @@
 		printf("\tUSAGE: %X\n", report_item->usage);
 		printf("\tUSAGE PAGE: %X\n", report_item->usage_page);
+		printf("\tLOGMIN: %X\n", report_item->logical_minimum);
+		printf("\tLOGMAX: %X\n", report_item->logical_maximum);		
+		printf("\tPHYMIN: %X\n", report_item->physical_minimum);		
+		printf("\tPHYMAX: %X\n", report_item->physical_maximum);				
 		printf("\n");		
 
@@ -563,4 +572,136 @@
 	return;
 }
+
+/** Parse and act upon a HID report.
+ *
+ * @see usb_hid_parse_report_descriptor
+ *
+ * @param parser Opaque HID report parser structure.
+ * @param data Data for the report.
+ * @param callbacks Callbacks for report actions.
+ * @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)
+{
+	/*
+	 *
+	 * 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;
+	
+}
+
+
+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;		
+	}
+
+	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);
+	
+}
 /**
  * @}
