Index: uspace/lib/usb/src/devdrv.c
===================================================================
--- uspace/lib/usb/src/devdrv.c	(revision d773285ffe7dee46caac6fd3fb53c959abdcec05)
+++ uspace/lib/usb/src/devdrv.c	(revision d8987b19dcb446b3842662825b1f9727cde5dae9)
@@ -251,5 +251,5 @@
 	    &dev->descriptors.configuration_size);
 	if (rc != EOK) {
-		usb_log_error("Failed retrieving configuration descriptor: %s.\n",
+		usb_log_error("Failed retrieving configuration descriptor: %s. %s\n",
 		    dev->ddf_dev->name, str_error(rc));
 		return rc;
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision d773285ffe7dee46caac6fd3fb53c959abdcec05)
+++ uspace/lib/usb/src/hidparser.c	(revision d8987b19dcb446b3842662825b1f9727cde5dae9)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief HID parser implementation.
+ * HID report descriptor and report data parser implementation.
  */
 #include <usb/classes/hidparser.h>
@@ -40,10 +40,16 @@
 #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
-
+/*
+ * Private descriptor parser functions
+ */
 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, usb_hid_report_path_t *usage_path);
@@ -58,10 +64,15 @@
 int usb_hid_report_reset_local_items();
 void usb_hid_free_report_list(link_t *head);
+
+/*
+ * Data translation private functions
+ */
 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);
+int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int32_t value);
 int usb_pow(int a, int b);
 
-
+// TODO: tohle ma bejt asi jinde
 int usb_pow(int a, int b)
 {
@@ -80,13 +91,16 @@
 
 /**
- *
+ * Initialize the report descriptor parser structure
+ *
+ * @param parser Report descriptor parser structure
+ * @return Error code
  */
 int usb_hid_parser_init(usb_hid_report_parser_t *parser)
 {
-   if(parser == NULL) {
-	return EINVAL;
-   }
-
-    list_initialize(&(parser->input));
+	if(parser == NULL) {
+		return EINVAL;
+	}
+
+	list_initialize(&(parser->input));
     list_initialize(&(parser->output));
     list_initialize(&(parser->feature));
@@ -164,10 +178,7 @@
 					// store current usage path
 					report_item->usage_path = usage_path;
-
-					// new current usage path 
-					tmp_usage_path = usb_hid_report_path();
 					
-					// copy old path to the new one
-					usb_hid_report_path_clone(tmp_usage_path, usage_path);
+					// clone path to the new one
+					tmp_usage_path = usb_hid_report_path_clone(usage_path);
 
 					// swap
@@ -304,4 +315,5 @@
 
 /**
+ * Parse one tag of the report descriptor
  *
  * @param Tag to parse
@@ -391,5 +403,4 @@
  * @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, usb_hid_report_path_t *usage_path)
@@ -520,5 +531,5 @@
  * Prints content of given list of report items.
  *
- * @param List of report items
+ * @param List of report items (usb_hid_report_item_t)
  * @return void
  */
@@ -552,8 +563,5 @@
 			path = path->next;
 		}
-		
-		
-//		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);		
@@ -570,7 +578,7 @@
 }
 /**
- * Prints content of given descriptor in human readable format.
- *
- * @param Parsed descriptor to print
+ * Prints content of given report descriptor in human readable format.
+ *
+ * @param parser Parsed descriptor to print
  * @return void
  */
@@ -595,5 +603,6 @@
  * Releases whole linked list of report items
  *
- * 
+ * @param head Head of list of report descriptor items (usb_hid_report_item_t)
+ * @return void
  */
 void usb_hid_free_report_list(link_t *head)
@@ -627,8 +636,8 @@
 }
 
-/** Free the HID report parser structure 
+/** Frees the HID report descriptor parser structure 
  *
  * @param parser Opaque HID report parser structure
- * @return Error code
+ * @return void
  */
 void usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
@@ -660,9 +669,4 @@
     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;
@@ -676,7 +680,6 @@
 		return EINVAL;
 	}
-
-	
-	// get the size of result keycodes array
+	
+	/* get the size of result array */
 	key_count = usb_hid_report_input_length(parser, path, flags);
 
@@ -685,5 +688,5 @@
 	}
 
-	// read data		
+	/* read data */
 	list_item = parser->input.next;	   
 	while(list_item != &(parser->input)) {
@@ -719,5 +722,12 @@
 }
 
-
+/**
+ * Translate data from the report as specified in report descriptor
+ *
+ * @param item Report descriptor item with definition of translation
+ * @param data Data to translate
+ * @param j Index of processed field in report descriptor item
+ * @return Translated data
+ */
 int usb_hid_translate_data(usb_hid_report_item_t *item, const uint8_t *data, size_t j)
 {
@@ -796,16 +806,24 @@
 }
 
-int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
+/**
+ *
+ *
+ * @param parser
+ * @param path
+ * @param flags
+ * @return
+ */
+size_t usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
 	usb_hid_report_path_t *path, int flags)
 {	
-	int ret = 0;
+	size_t ret = 0;
 	link_t *item;
 	usb_hid_report_item_t *report_item;
 
 	if(parser == NULL) {
-		return EINVAL;
-	}
-	
-	item = (&parser->input)->next;
+		return 0;
+	}
+	
+	item = parser->input.next;
 	while(&parser->input != item) {
 		report_item = list_get_instance(item, usb_hid_report_item_t, link);
@@ -824,4 +842,8 @@
 /**
  * 
+ * @param usage_path
+ * @param usage_page
+ * @param usage
+ * @return
  */
 int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, 
@@ -845,4 +867,6 @@
 /**
  *
+ * @param usage_path
+ * @return
  */
 void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
@@ -860,4 +884,6 @@
 /**
  *
+ * @param usage_path
+ * @return
  */
 void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
@@ -873,4 +899,8 @@
 /**
  *
+ * @param usage_path
+ * @param tag
+ * @param data
+ * @return
  */
 void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
@@ -894,5 +924,10 @@
 
 /**
- *
+ * 
+ *
+ * @param report_path
+ * @param path
+ * @param flags
+ * @return
  */
 int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, 
@@ -949,5 +984,5 @@
 			break;
 
-		/* given path must be the end of the report one*/
+		/* compare with only the end of path*/
 		case USB_HID_PATH_COMPARE_END:
 				report_link = report_path->link.prev;
@@ -992,4 +1027,5 @@
 /**
  *
+ * @return
  */
 usb_hid_report_path_t *usb_hid_report_path(void)
@@ -1009,4 +1045,6 @@
 /**
  *
+ * @param path
+ * @return void
  */
 void usb_hid_report_path_free(usb_hid_report_path_t *path)
@@ -1019,14 +1057,21 @@
 
 /**
- *
- */
-int	usb_hid_report_path_clone(usb_hid_report_path_t *new_usage_path, usb_hid_report_path_t *usage_path)
+ * Clone content of given usage path to the new one
+ *
+ * @param usage_path
+ * @return
+ */
+usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
 {
 	usb_hid_report_usage_path_t *path_item;
 	link_t *path_link;
-
+	usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
+
+	if(new_usage_path == NULL){
+		return NULL;
+	}
 	
 	if(list_empty(&usage_path->link)){
-		return EOK;
+		return new_usage_path;
 	}
 
@@ -1039,7 +1084,242 @@
 	}
 
+	return new_usage_path;
+}
+
+
+/*** OUTPUT API **/
+
+/** Allocates output report buffer
+ *
+ * @param parser
+ * @param size
+ * @return
+ */
+uint8_t *usb_hid_report_output(usb_hid_report_parser_t *parser, size_t *size)
+{
+	if(parser == NULL) {
+		*size = 0;
+		return NULL;
+	}
+	
+	// read the last output report item
+	usb_hid_report_item_t *last;
+	link_t *link;
+
+	link = parser->output.prev;
+	if(link != &parser->output) {
+		last = list_get_instance(link, usb_hid_report_item_t, link);
+		*size = (last->offset + (last->size * last->count)) / 8;
+
+		uint8_t *buffer = malloc(sizeof(uint8_t) * (*size));
+		memset(buffer, 0, sizeof(uint8_t) * (*size));
+		usb_log_debug("output buffer: %s\n", usb_debug_str_buffer(buffer, *size, 0));
+
+		return buffer;
+	}
+	else {
+		*size = 0;		
+		return NULL;
+	}
+}
+
+
+/** Frees output report buffer
+ *
+ * @param output Output report buffer
+ * @return
+ */
+void usb_hid_report_output_free(uint8_t *output)
+
+{
+	if(output != NULL) {
+		free (output);
+	}
+}
+
+/** Returns size of output for given usage path 
+ *
+ * @param parser
+ * @param path
+ * @param flags
+ * @return
+ */
+size_t usb_hid_report_output_size(usb_hid_report_parser_t *parser,
+                                  usb_hid_report_path_t *path, int flags)
+{
+	size_t ret = 0;
+	link_t *item;
+	usb_hid_report_item_t *report_item;
+
+	if(parser == NULL) {
+		return 0;
+	}
+	
+	item = parser->output.next;
+	while(&parser->output != item) {
+		report_item = list_get_instance(item, usb_hid_report_item_t, link);
+		if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
+		   (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
+			ret += report_item->count;
+		}
+
+		item = item->next;
+	} 
+
+	return ret;
+	
+}
+
+/** Updates the output report buffer by translated given data 
+ *
+ * @param parser
+ * @param path
+ * @param flags
+ * @param buffer
+ * @param size
+ * @param data
+ * @param data_size
+ * @return
+ */
+int usb_hid_report_output_translate(usb_hid_report_parser_t *parser,
+                                    usb_hid_report_path_t *path, int flags,
+                                    uint8_t *buffer, size_t size,
+                                    int32_t *data, size_t data_size)
+{
+	usb_hid_report_item_t *report_item;
+	link_t *item;	
+	size_t idx=0;
+	int i=0;
+	int32_t value=0;
+	int offset;
+	int length;
+	int32_t tmp_value;
+	
+	if(parser == NULL) {
+		return EINVAL;
+	}
+
+	usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
+	usb_log_debug("OUTPUT DATA[0]: %d, DATA[1]: %d, DATA[2]: %d\n", data[0], data[1], data[2]);
+
+	item = parser->output.next;	
+	while(item != &parser->output) {
+		report_item = list_get_instance(item, usb_hid_report_item_t, link);
+
+		for(i=0; i<report_item->count; i++) {
+
+			if(idx >= data_size) {
+				break;
+			}
+
+			if((USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0) ||
+				((report_item->usage_minimum == 0) && (report_item->usage_maximum == 0))) {
+					
+//				// variable item
+				value = usb_hid_translate_data_reverse(report_item, data[idx++]);
+				offset = report_item->offset + (i * report_item->size);
+				length = report_item->size;
+			}
+			else {
+				//bitmap
+				value += usb_hid_translate_data_reverse(report_item, data[idx++]);
+				offset = report_item->offset;
+				length = report_item->size * report_item->count;
+			}
+
+			if((offset/8) == ((offset+length-1)/8)) {
+				// je to v jednom bytu
+				if(((size_t)(offset/8) >= size) || ((size_t)(offset+length-1)/8) >= size) {
+					break; // TODO ErrorCode
+				}
+
+				size_t shift = offset%8;
+
+				value = value << shift;							
+				value = value & (((1 << length)-1) << shift);
+				
+				uint8_t mask = 0;
+				mask = 0xff - (((1 << length) - 1) << shift);
+				buffer[offset/8] = (buffer[offset/8] & mask) | value;
+			}
+			else {
+				// je to ve dvou!! FIXME: melo by to umet delsi jak 2
+
+				// konec prvniho -- dolni x bitu
+				tmp_value = value;
+				tmp_value = tmp_value & ((1 << (8-(offset%8)))-1);				
+				tmp_value = tmp_value << (offset%8);
+
+				uint8_t mask = 0;
+				mask = ~(((1 << (8-(offset%8)))-1) << (offset%8));
+				buffer[offset/8] = (buffer[offset/8] & mask) | tmp_value;
+
+				// a ted druhej -- hornich length-x bitu
+				value = value >> (8 - (offset % 8));
+				value = value & ((1 << (length - (8 - (offset % 8)))) - 1);
+				
+				mask = ((1 << (length - (8 - (offset % 8)))) - 1);
+				buffer[(offset+length-1)/8] = (buffer[(offset+length-1)/8] & mask) | value;
+			}
+
+		}
+
+		item = item->next;
+	}
+
+	usb_log_debug("OUTPUT BUFFER: %s\n", usb_debug_str_buffer(buffer,size, 0));
+
 	return EOK;
 }
 
+/**
+ *
+ * @param item
+ * @param value
+ * @return
+ */
+int32_t usb_hid_translate_data_reverse(usb_hid_report_item_t *item, int value)
+{
+	int ret=0;
+	int resolution;
+
+	if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) {
+		ret = item->logical_minimum;
+	}
+
+	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;
+		}
+		else {
+		    resolution = (item->logical_maximum - item->logical_minimum) /
+			((item->physical_maximum - item->physical_minimum) *
+			(usb_pow(10,(item->unit_exponent))));
+		}
+
+		ret = ((value - item->physical_minimum) * resolution) + item->logical_minimum;
+	}
+	else {
+		// bitmapa
+		if(value == 0) {
+			ret = 0;
+		}
+		else {
+			size_t bitmap_idx = (value - item->usage_minimum);
+			ret = 1 << bitmap_idx;
+		}
+	}
+
+
+	return ret;
+}
+
 
 /**
Index: uspace/lib/usb/src/request.c
===================================================================
--- uspace/lib/usb/src/request.c	(revision d773285ffe7dee46caac6fd3fb53c959abdcec05)
+++ uspace/lib/usb/src/request.c	(revision d8987b19dcb446b3842662825b1f9727cde5dae9)
@@ -529,5 +529,4 @@
 		return rc;
 	}
-
 	if (bare_config.descriptor_type != USB_DESCTYPE_CONFIGURATION) {
 		return ENOENT;
