Index: uspace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision e50cd7f06f4f69de26916ce998bb262dbcd8bec0)
+++ uspace/drv/usbhid/kbd/kbddev.c	(revision cfbbe1d3a9a94acf026279720b2b199d8893f400)
@@ -299,30 +299,33 @@
 		return;
 	}
-	
-	unsigned i = 0;
-	
+		
 	/* Reset the LED data. */
 	memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t));
-	
-	if ((kbd_dev->mods & KM_NUM_LOCK) && (i < kbd_dev->led_output_size)) {
-		kbd_dev->led_data[i++] = USB_HID_LED_NUM_LOCK;
-	}
-	
-	if ((kbd_dev->mods & KM_CAPS_LOCK) && (i < kbd_dev->led_output_size)) {
-		kbd_dev->led_data[i++] = USB_HID_LED_CAPS_LOCK;
-	}
-	
-	if ((kbd_dev->mods & KM_SCROLL_LOCK) 
-	    && (i < kbd_dev->led_output_size)) {
-		kbd_dev->led_data[i++] = USB_HID_LED_SCROLL_LOCK;
-	}
-
-	// TODO: COMPOSE and KANA
-	
-	usb_log_debug("Creating output report: %s\n", usb_debug_str_buffer ((uint8_t *)kbd_dev->led_data, kbd_dev->led_output_size * 4, 0));
-
-	usb_hid_report_output_set_data(hid_dev->parser, kbd_dev->led_path, 
-	                               USB_HID_PATH_COMPARE_END , kbd_dev->led_data, 
-	                               kbd_dev->led_output_size);
+	usb_log_debug("Creating output report:\n");
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling (hid_dev->parser, NULL,
+                kbd_dev->led_path, 
+				USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY | USB_HID_PATH_COMPARE_END,
+				USB_HID_REPORT_TYPE_OUTPUT);
+	while(field != NULL) {
+
+		if((field->usage == USB_HID_LED_NUM_LOCK) && (kbd_dev->mods & KM_NUM_LOCK)){
+			field->value = 1;
+		}
+
+		if((field->usage == USB_HID_LED_CAPS_LOCK) && (kbd_dev->mods & KM_CAPS_LOCK)){
+			field->value = 1;
+		}
+
+		if((field->usage == USB_HID_LED_SCROLL_LOCK) && (kbd_dev->mods & KM_SCROLL_LOCK)){
+			field->value = 1;
+		}
+		
+		field = usb_hid_report_get_sibling (hid_dev->parser, field,
+                kbd_dev->led_path, 
+				USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY | USB_HID_PATH_COMPARE_END,
+				USB_HID_REPORT_TYPE_OUTPUT);
+	}
+		
 	int rc = usb_hid_report_output_translate(hid_dev->parser, 0,
 	    kbd_dev->output_buffer, kbd_dev->output_size);
@@ -648,17 +651,25 @@
 	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
 	//usb_hid_report_path_set_report_id(path, 0);
-	
-	int rc = usb_hid_parse_report(hid_dev->parser, buffer, actual_size);	
+
+	uint8_t report_id;
+	int rc = usb_hid_parse_report(hid_dev->parser, buffer, actual_size, &report_id);	
+	usb_hid_report_path_set_report_id (path, report_id);
 	usb_hid_report_field_t *field = usb_hid_report_get_sibling(hid_dev->parser, 
 	                    NULL, path, USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
 						USB_HID_REPORT_TYPE_INPUT);
-	
+
+	unsigned i=0;
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
+
+	memset(kbd_dev->keys, 0, kbd_dev->key_count);
 	while(field != NULL) {
-		usb_log_debug("FIELD (%X) - VALUE(%X) USAGE(%X)\n", field, field->value, field->usage);
+		if((i < kbd_dev->key_count) && (field->value != 0)){
+			kbd_dev->keys[i++] = (uint8_t)field->usage;
+		}
 		field = usb_hid_report_get_sibling(hid_dev->parser, field, path, 
 		                                   USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
 		                                   USB_HID_REPORT_TYPE_INPUT);
 	}
-		
+	usb_kbd_process_keycodes(kbd_dev->keys, kbd_dev->key_count, report_id, hid_dev);
 	
 	usb_hid_report_path_free(path);
Index: uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision e50cd7f06f4f69de26916ce998bb262dbcd8bec0)
+++ uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision cfbbe1d3a9a94acf026279720b2b199d8893f400)
@@ -81,7 +81,8 @@
 	usb_hid_report_path_t *path = usb_hid_report_path();
 	usb_hid_report_path_append_item(path, 0xc, 0);
-	usb_hid_report_path_set_report_id(path, 0);
-	
-	int rc = usb_hid_parse_report(hid_dev->parser, buffer, buffer_size);
+
+	uint8_t report_id;
+	int rc = usb_hid_parse_report(hid_dev->parser, buffer, buffer_size, &report_id);
+	usb_hid_report_path_set_report_id(path, report_id);
 
 	usb_hid_report_field_t *field = usb_hid_report_get_sibling(hid_dev->parser, NULL, path, USB_HID_PATH_COMPARE_END , USB_HID_REPORT_TYPE_INPUT);
Index: uspace/drv/usbkbd/kbddev.c
===================================================================
--- uspace/drv/usbkbd/kbddev.c	(revision e50cd7f06f4f69de26916ce998bb262dbcd8bec0)
+++ uspace/drv/usbkbd/kbddev.c	(revision cfbbe1d3a9a94acf026279720b2b199d8893f400)
@@ -618,5 +618,6 @@
 	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
 
-	int rc = usb_hid_parse_report(kbd_dev->parser, buffer, actual_size);
+	uint8_t report_id;
+	int rc = usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, &report_id);
 	usb_hid_descriptor_print (kbd_dev->parser);
 
Index: uspace/lib/usb/include/usb/classes/hidparser.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidparser.h	(revision e50cd7f06f4f69de26916ce998bb262dbcd8bec0)
+++ uspace/lib/usb/include/usb/classes/hidparser.h	(revision cfbbe1d3a9a94acf026279720b2b199d8893f400)
@@ -119,4 +119,5 @@
 
 	int use_report_ids;
+	uint8_t last_report_id;
 	
 } usb_hid_report_t;
@@ -279,5 +280,5 @@
  */
 /** */
-int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size);
+int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, size_t size, uint8_t *report_id);
 
 /** */
@@ -318,4 +319,7 @@
 
 usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type);
+
+uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type);
+
 
 /*
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision e50cd7f06f4f69de26916ce998bb262dbcd8bec0)
+++ uspace/lib/usb/src/hidparser.c	(revision cfbbe1d3a9a94acf026279720b2b199d8893f400)
@@ -81,5 +81,5 @@
 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_field_t *item, const uint8_t *data, size_t j);
+int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
 uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, int32_t value);
 int usb_pow(int a, int b);
@@ -151,5 +151,5 @@
 		list_initialize(&field->link);
 
-		/* fill the attributes */
+		/* fill the attributes */		
 		field->collection_path = path;
 		field->logical_minimum = report_item->logical_minimum;
@@ -157,4 +157,5 @@
 		field->physical_minimum = report_item->physical_minimum;
 		field->physical_maximum = report_item->physical_maximum;
+
 		field->usage_minimum = report_item->usage_minimum;
 		field->usage_maximum = report_item->usage_maximum;
@@ -165,8 +166,8 @@
 			field->usage_page = report_item->usage_page;
 		}
-		
-		if(report_item->usages_count > 0 && ((report_item->usage_minimum = 0) && (report_item->usage_maximum = 0))) {
+
+		if(report_item->usages_count > 0 && ((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
 			if(i < report_item->usages_count){
-				if((report_item->usages[i] & 0xFF00) > 0){
+				if((report_item->usages[i] & 0xFF00) != 0){
 					field->usage_page = (report_item->usages[i] >> 16);					
 					field->usage = (report_item->usages[i] & 0xFF);
@@ -179,5 +180,15 @@
 				field->usage = report_item->usages[report_item->usages_count - 1];
 			}
-		}		
+		}	
+
+		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->size = report_item->size;
@@ -788,10 +799,9 @@
  */ 
 int usb_hid_parse_report(const usb_hid_report_t *report,  
-    const uint8_t *data, size_t size)
+    const uint8_t *data, size_t size, uint8_t *report_id)
 {
 	link_t *list_item;
 	usb_hid_report_field_t *item;
 
-	uint8_t report_id = 0;
 	usb_hid_report_description_t *report_des;
 	usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
@@ -802,8 +812,12 @@
 
 	if(report->use_report_ids != 0) {
-		report_id = data[0];
-	}
-
-	report_des = usb_hid_report_find_description(report, report_id, type);
+		*report_id = data[0];
+	}	
+	else {
+		*report_id = 0;
+	}
+
+
+	report_des = usb_hid_report_find_description(report, *report_id, type);
 
 	/* read data */
@@ -813,22 +827,16 @@
 		item = list_get_instance(list_item, usb_hid_report_field_t, link);
 
-		if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) {
+		if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
 			
-			if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
-			   ((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
-
+			if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
+
+				// array
+				item->value = usb_hid_translate_data(item, data);
+			    item->usage = (item->value - item->physical_minimum) + item->usage_minimum;
+			}
+			else {
 				// variable item
-				item->value = usb_hid_translate_data(item, data,0);
-
-				// array item ???
-				if(!((item->usage_minimum == 0) && (item->usage_maximum == 0))) {
-					item->usage = item->value + item->usage_minimum;
-				}
-			}
-			else {
-				// bitmapa
-				// TODO: overit jestli vraci hodnoty podle phy min/max 
-				item->value = usb_hid_translate_data(item, data, 0);
-			}			
+				item->value = usb_hid_translate_data(item, data);				
+			}				
 		}
 		list_item = list_item->next;
@@ -847,5 +855,5 @@
  * @return Translated data
  */
-int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data, size_t j)
+int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
 {
 	int resolution;
@@ -862,8 +870,9 @@
 	}
 
-	if((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
+	if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
 		item->physical_minimum = item->logical_minimum;
-		item->physical_maximum = item->logical_maximum;		
-	}
+		item->physical_maximum = item->logical_maximum;			
+	}
+	
 
 	if(item->physical_maximum == item->physical_minimum){
@@ -876,5 +885,5 @@
 	}
 
-	offset = item->offset + (j * item->size);
+	offset = item->offset;
 	// FIXME
 	if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
@@ -914,5 +923,4 @@
 		value = (uint32_t)value;
 	}
-
 
 	return (int)(((value - item->logical_minimum) / resolution) + item->physical_minimum);
@@ -1393,5 +1401,5 @@
 
 	usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
-
+	
 	usb_hid_report_description_t *report_des;
 	report_des = usb_hid_report_find_description (report, report_id, USB_HID_REPORT_TYPE_OUTPUT);
@@ -1405,8 +1413,7 @@
 		report_item = list_get_instance(item, usb_hid_report_field_t, link);
 
-			if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) ||
-				((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
+			if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) {
 					
-				// variable item
+				// array
 				value = usb_hid_translate_data_reverse(report_item, report_item->value);
 				offset = report_item->offset;
@@ -1414,6 +1421,6 @@
 			}
 			else {
-				//bitmap
-				value += usb_hid_translate_data_reverse(report_item, report_item->value);
+				// variable item
+				value  = usb_hid_translate_data_reverse(report_item, report_item->value);
 				offset = report_item->offset;
 				length = report_item->size;
@@ -1462,7 +1469,10 @@
 
 
+		// reset value
+		report_item->value = 0;
+		
 		item = item->next;
 	}
-
+	
 	usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
 
@@ -1485,12 +1495,13 @@
 	}
 
+	if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
+		item->physical_minimum = item->logical_minimum;
+		item->physical_maximum = item->logical_maximum;			
+	}
+	
+
 	if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0)) {
 
 		// variable item
-		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;
@@ -1568,7 +1579,13 @@
 			if(usb_hid_report_compare_usage_path (field->collection_path, path, 
 		                                      flags) == EOK) {
-
 				if(data_idx < data_size) {
-					field->value = data[data_idx++];
+					if((data[data_idx] >= field->physical_minimum) && (data[data_idx] >= field->physical_minimum)) {
+						field->value = data[data_idx];
+					}
+					else {
+						return ERANGE;
+					}
+
+					data_idx++;
 				}
 				else {
@@ -1626,5 +1643,4 @@
 		if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
 			usb_hid_report_remove_last_item (field->collection_path);
-			usb_log_debug("....OK\n");
 			return field;
 		}
@@ -1636,4 +1652,32 @@
 	return NULL;
 }
+
+uint8_t usb_hid_report_get_report_id(usb_hid_report_t *report, uint8_t report_id, usb_hid_report_type_t type)
+{
+	if(report == NULL){
+		return 0;
+	}
+
+	usb_hid_report_description_t *report_des;
+	link_t *report_it;
+	
+	if(report_id == 0) {
+		report_it = usb_hid_report_find_description (report, report_id, type)->link.next;		
+	}
+	else {
+		report_it = report->reports.next;
+	}
+
+	while(report_it != &report->reports) {
+		report_des = list_get_instance(report_it, usb_hid_report_description_t, link);
+		if(report_des->type == type){
+			return report_des->report_id;
+		}
+	}
+
+	return 0;
+}
+
+
 /**
  * @}
