Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision d93b3e36bf0cc42d6485a352380282177488c228)
+++ uspace/lib/usb/Makefile	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
@@ -50,4 +50,6 @@
 	src/usb.c \
 	src/usbdevice.c \
+	src/hidreq.c \
+	src/hidreport.c \
 	src/host/device_keeper.c \
 	src/host/batch.c
Index: uspace/lib/usb/include/usb/classes/hidparser.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidparser.h	(revision d93b3e36bf0cc42d6485a352380282177488c228)
+++ uspace/lib/usb/include/usb/classes/hidparser.h	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
@@ -70,6 +70,18 @@
  * Description of path of usage pages and usages in report descriptor
  */
+#define USB_HID_PATH_COMPARE_STRICT				0
+#define USB_HID_PATH_COMPARE_END				1
+#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY	4
+
 typedef struct {
 	int32_t usage_page;
+	int32_t usage;
+
+	link_t link;
+} usb_hid_report_usage_path_t;
+
+typedef struct {
+	int depth;	
+	link_t link;
 } usb_hid_report_path_t;
 
@@ -79,6 +91,4 @@
 typedef struct {
 	int32_t id;
-	int32_t usage_page;
-	int32_t	usage;	
 	int32_t usage_minimum;
 	int32_t usage_maximum;
@@ -107,4 +117,5 @@
 	uint8_t item_flags;
 
+	usb_hid_report_path_t *usage_path;
 	link_t link;
 } usb_hid_report_item_t;
@@ -117,5 +128,4 @@
 	link_t feature;
 } usb_hid_report_parser_t;	
-
 
 
@@ -194,8 +204,9 @@
 int usb_hid_parse_report(const usb_hid_report_parser_t *parser,  
     const uint8_t *data, size_t size,
+    usb_hid_report_path_t *path, int flags,
     const usb_hid_report_in_callbacks_t *callbacks, void *arg);
 
 int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
-	const usb_hid_report_path_t *path);
+	usb_hid_report_path_t *path, int flags);
 
 
@@ -204,4 +215,20 @@
 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
 
+/* usage path functions */
+usb_hid_report_path_t *usb_hid_report_path(void);
+void usb_hid_report_path_free(usb_hid_report_path_t *path);
+int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, int32_t usage_page, int32_t usage);
+void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path);
+void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path);
+void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data);
+int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, usb_hid_report_path_t *path, int flags);
+int	usb_hid_report_path_clone(usb_hid_report_path_t *new_usage_path, usb_hid_report_path_t *usage_path);
+
+
+// output
+//	- funkce co vrati cesty poli v output reportu
+//	- funkce co pro danou cestu nastavi data
+//	- finalize
+
 #endif
 /**
Index: uspace/lib/usb/include/usb/classes/hidreport.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidreport.h	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
+++ uspace/lib/usb/include/usb/classes/hidreport.h	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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
+ * USB HID report parser initialization from descriptors.
+ */
+
+#ifndef LIBUSB_HIDREPORT_H_
+#define LIBUSB_HIDREPORT_H_
+
+#include <usb/devdrv.h>
+#include <usb/classes/hidparser.h>
+
+/**
+ * Retrieves the Report descriptor from the USB device and initializes the
+ * report parser.
+ *
+ * \param dev USB device representing a HID device.
+ * \param parser HID Report parser.
+ *
+ * \retval EOK if successful.
+ * \retval EINVAL if one of the parameters is not given (is NULL).
+ * \retval ENOENT if there are some descriptors missing.
+ * \retval ENOMEM if an error with allocation occured.
+ * \retval EINVAL if the Report descriptor's size does not match the size 
+ *         from the interface descriptor.
+ * \return Other value inherited from function usb_pipe_start_session(),
+ *         usb_pipe_end_session() or usb_request_get_descriptor().
+ */
+int usb_hid_process_report_descriptor(usb_device_t *dev, 
+    usb_hid_report_parser_t *parser);
+
+#endif /* LIBUSB_HIDREPORT_H_ */
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/classes/hidreq.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidreq.h	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
+++ uspace/lib/usb/include/usb/classes/hidreq.h	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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
+ * HID class-specific requests.
+ */
+
+#ifndef USB_KBD_HIDREQ_H_
+#define USB_KBD_HIDREQ_H_
+
+#include <stdint.h>
+
+#include <usb/classes/hid.h>
+#include <usb/pipes.h>
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size);
+
+int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t protocol);
+
+int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration);
+
+int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size, 
+    size_t *actual_size);
+
+int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t *protocol);
+
+int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration);
+
+/*----------------------------------------------------------------------------*/
+
+#endif /* USB_KBD_HIDREQ_H_ */
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/request.h
===================================================================
--- uspace/lib/usb/include/usb/request.h	(revision d93b3e36bf0cc42d6485a352380282177488c228)
+++ uspace/lib/usb/include/usb/request.h	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
@@ -41,4 +41,13 @@
 #include <usb/pipes.h>
 #include <usb/descriptor.h>
+
+/** USB device status - device is self powered (opposed to bus powered). */
+#define USB_DEVICE_STATUS_SELF_POWERED ((uint16_t)(1 << 0))
+
+/** USB device status - remote wake-up signaling is enabled. */
+#define USB_DEVICE_STATUS_REMOTE_WAKEUP ((uint16_t)(1 << 1))
+
+/** USB endpoint status - endpoint is halted (stalled). */
+#define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0))
 
 /** Standard device request. */
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision d93b3e36bf0cc42d6485a352380282177488c228)
+++ uspace/lib/usb/src/hidparser.c	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
@@ -47,11 +47,11 @@
 
 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_item_t *report_item, usb_hid_report_path_t *usage_path);
 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);
+                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
 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_item_t *report_item, usb_hid_report_path_t *usage_path);
 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);
+                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path);
 
 void usb_hid_descriptor_print_list(link_t *head);
@@ -63,4 +63,5 @@
 int usb_pow(int a, int b);
 
+
 int usb_pow(int a, int b)
 {
@@ -84,5 +85,5 @@
 {
    if(parser == NULL) {
-	return -1;
+	return EINVAL;
    }
 
@@ -110,5 +111,7 @@
 	int ret;
 	usb_hid_report_item_t *report_item=0;
-	usb_hid_report_item_t *new_report_item;
+	usb_hid_report_item_t *new_report_item;	
+	usb_hid_report_path_t *usage_path;
+	usb_hid_report_path_t *tmp_usage_path;
 
 	size_t offset_input=0;
@@ -117,16 +120,27 @@
 	
 
+	/* parser structure initialization*/
+	if(usb_hid_parser_init(parser) != EOK) {
+		return EINVAL;
+	}
+	
+
+	/*report item initialization*/
 	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));	
-
+	list_initialize(&(report_item->link));	
+
+	/* usage path context initialization */
+	if(!(usage_path=usb_hid_report_path())){
+		return ENOMEM;
+	}
+	
 	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
+				return EINVAL; // TODO ERROR CODE
 			}
 			
@@ -141,10 +155,24 @@
 			
 			ret = usb_hid_report_parse_tag(tag,class,data+i+1,
-			                         item_size,report_item);
+			                               item_size,report_item, usage_path);
 			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);
+					usb_log_debug("\nNEW REPORT ITEM: %X",ret);
+
+					// 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);
+
+					// swap
+					usage_path = tmp_usage_path;
+					tmp_usage_path = NULL;
+
 					
 					switch(tag) {
@@ -184,5 +212,5 @@
 					link_initialize(&(new_report_item->link));
 					report_item = new_report_item;
-					
+										
 					break;
 				case USB_HID_REPORT_TAG_PUSH:
@@ -284,5 +312,5 @@
  */
 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_item_t *report_item, usb_hid_report_path_t *usage_path)
 {	
 	int ret;
@@ -291,5 +319,5 @@
 		case USB_HID_TAG_CLASS_MAIN:
 
-			if((ret=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, usage_path)) == EOK) {
 				return USB_HID_NEW_REPORT_ITEM;
 			}
@@ -301,9 +329,9 @@
 
 		case USB_HID_TAG_CLASS_GLOBAL:	
-			return usb_hid_report_parse_global_tag(tag,data,item_size,report_item);
+			return usb_hid_report_parse_global_tag(tag,data,item_size,report_item, usage_path);
 			break;
 
 		case USB_HID_TAG_CLASS_LOCAL:			
-			return usb_hid_report_parse_local_tag(tag,data,item_size,report_item);
+			return usb_hid_report_parse_local_tag(tag,data,item_size,report_item, usage_path);
 			break;
 		default:
@@ -323,6 +351,6 @@
 
 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)
-{
+                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
+{		
 	switch(tag)
 	{
@@ -335,10 +363,14 @@
 			
 		case USB_HID_REPORT_TAG_COLLECTION:
-			// TODO
+			usb_hid_report_path_append_item(usage_path, 0, 0);
+						
 			return USB_HID_NO_ACTION;
 			break;
 			
 		case USB_HID_REPORT_TAG_END_COLLECTION:
-			/* should be ignored */
+			// TODO
+			// znici posledni uroven ve vsech usage paths
+			// otazka jestli nema nicit dve, respektive novou posledni vynulovat?
+			usb_hid_report_remove_last_item(usage_path);
 			return USB_HID_NO_ACTION;
 			break;
@@ -361,5 +393,5 @@
 
 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_item_t *report_item, usb_hid_report_path_t *usage_path)
 {
 	// TODO take care about the bit length of data
@@ -367,5 +399,7 @@
 	{
 		case USB_HID_REPORT_TAG_USAGE_PAGE:
-			report_item->usage_page = usb_hid_report_tag_data_int32(data,item_size);
+			// zmeni to jenom v poslednim poli aktualni usage path
+			usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_GLOBAL,
+				usb_hid_report_tag_data_int32(data,item_size));
 			break;
 		case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
@@ -418,10 +452,11 @@
  */
 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)
+                             usb_hid_report_item_t *report_item, usb_hid_report_path_t *usage_path)
 {
 	switch(tag)
 	{
 		case USB_HID_REPORT_TAG_USAGE:
-			report_item->usage = usb_hid_report_tag_data_int32(data,item_size);
+			usb_hid_report_set_last_item(usage_path, USB_HID_TAG_CLASS_LOCAL,
+				usb_hid_report_tag_data_int32(data,item_size));
 			break;
 		case USB_HID_REPORT_TAG_USAGE_MINIMUM:
@@ -491,4 +526,6 @@
 {
 	usb_hid_report_item_t *report_item;
+	usb_hid_report_usage_path_t *path_item;
+	link_t *path;
 	link_t *item;
 	
@@ -507,6 +544,16 @@
 		usb_log_debug("\tCONSTANT/VAR: %X\n", USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags));
 		usb_log_debug("\tVARIABLE/ARRAY: %X\n", USB_HID_ITEM_FLAG_VARIABLE(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("\tUSAGE PATH:\n");
+
+		path = report_item->usage_path->link.next;
+		while(path != &report_item->usage_path->link)	{
+			path_item = list_get_instance(path, usb_hid_report_usage_path_t, link);
+			usb_log_debug("\t\tUSAGE PAGE: %X, USAGE: %X\n", path_item->usage_page, path_item->usage);
+			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);		
@@ -530,4 +577,8 @@
 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser)
 {
+	if(parser == NULL) {
+		return;
+	}
+	
 	usb_log_debug("INPUT:\n");
 	usb_hid_descriptor_print_list(&parser->input);
@@ -561,4 +612,10 @@
 	
 	    report_item = list_get_instance(next, usb_hid_report_item_t, link);
+
+		while(!list_empty(&report_item->usage_path->link)) {
+			usb_hid_report_remove_last_item(report_item->usage_path);
+		}
+
+		
 	    next = next->next;
 	    
@@ -600,4 +657,5 @@
 int usb_hid_parse_report(const usb_hid_report_parser_t *parser,  
     const uint8_t *data, size_t size,
+    usb_hid_report_path_t *path, int flags,
     const usb_hid_report_in_callbacks_t *callbacks, void *arg)
 {
@@ -615,8 +673,11 @@
 	size_t j=0;
 
+	if(parser == NULL) {
+		return EINVAL;
+	}
+
+	
 	// get the size of result keycodes array
-	usb_hid_report_path_t path;
-	path.usage_page = BAD_HACK_USAGE_PAGE;
-	key_count = usb_hid_report_input_length(parser, &path);
+	key_count = usb_hid_report_input_length(parser, path, flags);
 
 	if(!(keys = malloc(sizeof(uint8_t) * key_count))){
@@ -629,6 +690,6 @@
 
 		item = list_get_instance(list_item, usb_hid_report_item_t, link);
-		if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) &&
-		   (item->usage_page == path.usage_page)) {
+		if(!USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) && 
+		   (usb_hid_report_compare_usage_path(item->usage_path, path, flags) == EOK)) {
 			for(j=0; j<(size_t)(item->count); j++) {
 				if((USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) ||
@@ -640,5 +701,5 @@
 					// bitmapa
 					if((item_value = usb_hid_translate_data(item, data, j)) != 0) {
-						keys[i++] = j + item->usage_minimum;
+						keys[i++] = (item->count - 1 - j) + item->usage_minimum;
 					}
 					else {
@@ -736,15 +797,19 @@
 
 int usb_hid_report_input_length(const usb_hid_report_parser_t *parser,
-	const usb_hid_report_path_t *path)
-{
+	usb_hid_report_path_t *path, int flags)
+{	
 	int ret = 0;
 	link_t *item;
 	usb_hid_report_item_t *report_item;
 
+	if(parser == NULL) {
+		return EINVAL;
+	}
+	
 	item = (&parser->input)->next;
 	while(&parser->input != item) {
 		report_item = list_get_instance(item, usb_hid_report_item_t, link);
 		if(!USB_HID_ITEM_FLAG_CONSTANT(report_item->item_flags) &&
-		   (report_item->usage_page == path->usage_page)) {
+		   (usb_hid_report_compare_usage_path(report_item->usage_path, path, flags) == EOK)) {
 			ret += report_item->count;
 		}
@@ -757,4 +822,224 @@
 
 
+/**
+ * 
+ */
+int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, 
+                                    int32_t usage_page, int32_t usage)
+{	
+	usb_hid_report_usage_path_t *item;
+
+	if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
+		return ENOMEM;
+	}
+	list_initialize(&item->link);
+
+	item->usage = usage;
+	item->usage_page = usage_page;
+	
+	list_append (&usage_path->link, &item->link);
+	usage_path->depth++;
+	return EOK;
+}
+
+/**
+ *
+ */
+void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
+{
+	usb_hid_report_usage_path_t *item;
+	
+	if(!list_empty(&usage_path->link)){
+		item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);		
+		list_remove(usage_path->link.prev);
+		usage_path->depth--;
+		free(item);
+	}
+}
+
+/**
+ *
+ */
+void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
+{
+	usb_hid_report_usage_path_t *item;
+	
+	if(!list_empty(&usage_path->link)){	
+		item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
+		memset(item, 0, sizeof(usb_hid_report_usage_path_t));
+	}
+}
+
+/**
+ *
+ */
+void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, int32_t tag, int32_t data)
+{
+	usb_hid_report_usage_path_t *item;
+	
+	if(!list_empty(&usage_path->link)){	
+		item = list_get_instance(usage_path->link.prev, usb_hid_report_usage_path_t, link);
+
+		switch(tag) {
+			case USB_HID_TAG_CLASS_GLOBAL:
+				item->usage_page = data;
+				break;
+			case USB_HID_TAG_CLASS_LOCAL:
+				item->usage = data;
+				break;
+		}
+	}
+	
+}
+
+/**
+ *
+ */
+int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, 
+                                      usb_hid_report_path_t *path,
+                                      int flags)
+{
+	usb_hid_report_usage_path_t *report_item;
+	usb_hid_report_usage_path_t *path_item;
+
+	link_t *report_link;
+	link_t *path_link;
+
+	int only_page;
+
+	if(path->depth == 0){
+		return EOK;
+	}
+
+
+	if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){
+		flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
+	}
+	
+	switch(flags){
+		/* path must be completly identical */
+		case USB_HID_PATH_COMPARE_STRICT:
+				if(report_path->depth != path->depth){
+					return 1;
+				}
+
+				report_link = report_path->link.next;
+				path_link = path->link.next;
+			
+				while((report_link != &report_path->link) && (path_link != &path->link)) {
+					report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
+					path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);		
+
+					if((report_item->usage_page != path_item->usage_page) || 
+					   ((only_page == 0) && (report_item->usage != path_item->usage))) {
+						   return 1;
+					} else {
+						report_link = report_link->next;
+						path_link = path_link->next;			
+					}
+			
+				}
+
+				if((report_link == &report_path->link) && (path_link == &path->link)) {
+					return EOK;
+				}
+				else {
+					return 1;
+				}						
+			break;
+
+		/* given path must be the end of the report one*/
+		case USB_HID_PATH_COMPARE_END:
+				report_link = report_path->link.prev;
+				path_link = path->link.prev;
+
+				if(list_empty(&path->link)){
+					return EOK;
+				}
+			
+				while((report_link != &report_path->link) && (path_link != &path->link)) {
+					report_item = list_get_instance(report_link, usb_hid_report_usage_path_t, link);
+					path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);		
+
+					if((report_item->usage_page != path_item->usage_page) || 
+					   ((only_page == 0) && (report_item->usage != path_item->usage))) {
+						   return 1;
+					} else {
+						report_link = report_link->prev;
+						path_link = path_link->prev;			
+					}
+			
+				}
+
+				if(path_link == &path->link) {
+					return EOK;
+				}
+				else {
+					return 1;
+				}						
+			
+			break;
+
+		default:
+			return EINVAL;
+	}
+	
+	
+	
+	
+}
+
+/**
+ *
+ */
+usb_hid_report_path_t *usb_hid_report_path(void)
+{
+	usb_hid_report_path_t *path;
+	path = malloc(sizeof(usb_hid_report_path_t));
+	if(!path){
+		return NULL;
+	}
+	else {
+		path->depth = 0;
+		list_initialize(&path->link);
+		return path;
+	}
+}
+
+/**
+ *
+ */
+void usb_hid_report_path_free(usb_hid_report_path_t *path)
+{
+	while(!list_empty(&path->link)){
+		usb_hid_report_remove_last_item(path);
+	}
+}
+
+
+/**
+ *
+ */
+int	usb_hid_report_path_clone(usb_hid_report_path_t *new_usage_path, usb_hid_report_path_t *usage_path)
+{
+	usb_hid_report_usage_path_t *path_item;
+	link_t *path_link;
+
+	
+	if(list_empty(&usage_path->link)){
+		return EOK;
+	}
+
+	path_link = usage_path->link.next;
+	while(path_link != &usage_path->link) {
+		path_item = list_get_instance(path_link, usb_hid_report_usage_path_t, link);
+		usb_hid_report_path_append_item (new_usage_path, path_item->usage_page, path_item->usage);
+
+		path_link = path_link->next;
+	}
+
+	return EOK;
+}
+
 
 /**
Index: uspace/lib/usb/src/hidreport.c
===================================================================
--- uspace/lib/usb/src/hidreport.c	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
+++ uspace/lib/usb/src/hidreport.c	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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
+ * USB HID keyboard device structure and API.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/debug.h>
+#include <usb/classes/hidparser.h>
+#include <usb/dp.h>
+#include <usb/devdrv.h>
+#include <usb/pipes.h>
+#include <usb/classes/hid.h>
+#include <usb/descriptor.h>
+#include <usb/request.h>
+
+#include <usb/classes/hidreport.h>
+
+static int usb_hid_get_report_descriptor(usb_device_t *dev, 
+    uint8_t **report_desc, size_t *size)
+{
+	assert(report_desc != NULL);
+	assert(size != NULL);
+	
+	usb_dp_parser_t parser =  {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+	
+	usb_dp_parser_data_t parser_data = {
+		.data = dev->descriptors.configuration,
+		.size = dev->descriptors.configuration_size,
+		.arg = NULL
+	};
+	
+	/*
+	 * First nested descriptor of the configuration descriptor.
+	 */
+	uint8_t *d = 
+	    usb_dp_get_nested_descriptor(&parser, &parser_data, 
+	    dev->descriptors.configuration);
+	
+	/*
+	 * Find the interface descriptor corresponding to our interface number.
+	 */
+	int i = 0;
+	while (d != NULL && i < dev->interface_no) {
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		    dev->descriptors.configuration, d);
+	}
+	
+	if (d == NULL) {
+		usb_log_error("The %d. interface descriptor not found!\n",
+		    dev->interface_no);
+		return ENOENT;
+	}
+	
+	/*
+	 * First nested descriptor of the interface descriptor.
+	 */
+	uint8_t *iface_desc = d;
+	d = usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc);
+	
+	/*
+	 * Search through siblings until the HID descriptor is found.
+	 */
+	while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) {
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		    iface_desc, d);
+	}
+	
+	if (d == NULL) {
+		usb_log_fatal("No HID descriptor found!\n");
+		return ENOENT;
+	}
+	
+	if (*d != sizeof(usb_standard_hid_descriptor_t)) {
+		usb_log_error("HID descriptor hass wrong size (%u, expected %u"
+		    ")\n", *d, sizeof(usb_standard_hid_descriptor_t));
+		return EINVAL;
+	}
+	
+	usb_standard_hid_descriptor_t *hid_desc = 
+	    (usb_standard_hid_descriptor_t *)d;
+	
+	uint16_t length =  hid_desc->report_desc_info.length;
+	size_t actual_size = 0;
+	
+	/*
+	 * Start session for the control transfer.
+	 */
+	int sess_rc = usb_pipe_start_session(&dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	/*
+	 * Allocate space for the report descriptor.
+	 */
+	*report_desc = (uint8_t *)malloc(length);
+	if (*report_desc == NULL) {
+		usb_log_error("Failed to allocate space for Report descriptor."
+		    "\n");
+		return ENOMEM;
+	}
+	
+	usb_log_debug("Getting Report descriptor, expected size: %u\n", length);
+	
+	/*
+	 * Get the descriptor from the device.
+	 */
+	int rc = usb_request_get_descriptor(&dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DESCTYPE_HID_REPORT, 0, dev->interface_no,
+	    *report_desc, length, &actual_size);
+
+	if (rc != EOK) {
+		free(*report_desc);
+		*report_desc = NULL;
+		return rc;
+	}
+
+	if (actual_size != length) {
+		free(*report_desc);
+		*report_desc = NULL;
+		usb_log_error("Report descriptor has wrong size (%u, expected "
+		    "%u)\n", actual_size, length);
+		return EINVAL;
+	}
+	
+	/*
+	 * End session for the control transfer.
+	 */
+	sess_rc = usb_pipe_end_session(&dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to end a session: %s.\n",
+		    str_error(sess_rc));
+		free(*report_desc);
+		*report_desc = NULL;
+		return sess_rc;
+	}
+	
+	*size = length;
+	
+	usb_log_debug("Done.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_hid_process_report_descriptor(usb_device_t *dev, 
+    usb_hid_report_parser_t *parser)
+{
+	if (dev == NULL || parser == NULL) {
+		usb_log_error("Failed to process Report descriptor: wrong "
+		    "parameters given.\n");
+		return EINVAL;
+	}
+	
+	uint8_t *report_desc = NULL;
+	size_t report_size;
+	
+	int rc = usb_hid_get_report_descriptor(dev, &report_desc, 
+	    &report_size);
+	
+	if (rc != EOK) {
+		usb_log_error("Problem with getting Report descriptor: %s.\n",
+		    str_error(rc));
+		if (report_desc != NULL) {
+			free(report_desc);
+		}
+		return rc;
+	}
+	
+	assert(report_desc != NULL);
+	
+	rc = usb_hid_parse_report_descriptor(parser, report_desc, report_size);
+	if (rc != EOK) {
+		usb_log_error("Problem parsing Report descriptor: %s.\n",
+		    str_error(rc));
+		free(report_desc);
+		return rc;
+	}
+	
+	usb_hid_descriptor_print(parser);
+	free(report_desc);
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/hidreq.c
===================================================================
--- uspace/lib/usb/src/hidreq.c	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
+++ uspace/lib/usb/src/hidreq.c	(revision b8d453ec72e401e6dcf16ce9063cf7b3cbbc97ab)
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * HID class-specific requests.
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/classes/hid.h>
+#include <usb/debug.h>
+#include <usb/request.h>
+#include <usb/pipes.h>
+
+#include <usb/classes/hidreq.h>
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Set Report request to the HID device.
+ *
+ * @param hid_dev HID device to send the request to.
+ * @param type Type of the report.
+ * @param buffer Report data.
+ * @param buf_size Report data size (in bytes).
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from one of functions 
+ *         usb_pipe_start_session(), usb_pipe_end_session(),
+ *         usb_control_request_set().
+ */
+int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	uint16_t value = 0;
+	value |= (type << 8);
+
+	usb_log_debug("Sending Set_Report request to the device.\n");
+	
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Set Protocol request to the HID device.
+ *
+ * @param hid_dev HID device to send the request to.
+ * @param protocol Protocol to set.
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from one of functions 
+ *         usb_pipe_start_session(), usb_pipe_end_session(),
+ *         usb_control_request_set().
+ */
+int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
+    usb_hid_protocol_t protocol)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Set_Protocol request to the device ("
+	    "protocol: %d, iface: %d).\n", protocol, iface_no);
+	
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Set Idle request to the HID device.
+ *
+ * @param hid_dev HID device to send the request to.
+ * @param duration Duration value (is multiplicated by 4 by the device to
+ *                 get real duration in miliseconds).
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from one of functions 
+ *         usb_pipe_start_session(), usb_pipe_end_session(),
+ *         usb_control_request_set().
+ */
+int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Set_Idle request to the device ("
+	    "duration: %u, iface: %d).\n", duration, iface_no);
+	
+	uint16_t value = duration << 8;
+	
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Get Report request to the HID device.
+ *
+ * @param[in] hid_dev HID device to send the request to.
+ * @param[in] type Type of the report.
+ * @param[in][out] buffer Buffer for the report data.
+ * @param[in] buf_size Size of the buffer (in bytes).
+ * @param[out] actual_size Actual size of report received from the device 
+ *                         (in bytes).
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from one of functions 
+ *         usb_pipe_start_session(), usb_pipe_end_session(),
+ *         usb_control_request_set().
+ */
+int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size, 
+    size_t *actual_size)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	uint16_t value = 0;
+	value |= (type << 8);
+	
+	usb_log_debug("Sending Get_Report request to the device.\n");
+	
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_REPORT, value, iface_no, buffer, buf_size,
+	    actual_size);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Get Protocol request to the HID device.
+ *
+ * @param[in] hid_dev HID device to send the request to.
+ * @param[out] protocol Current protocol of the device.
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from one of functions 
+ *         usb_pipe_start_session(), usb_pipe_end_session(),
+ *         usb_control_request_set().
+ */
+int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t *protocol)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Get_Protocol request to the device ("
+	    "iface: %d).\n", iface_no);
+	
+	uint8_t buffer[1];
+	size_t actual_size = 0;
+	
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	if (actual_size != 1) {
+		usb_log_warning("Wrong data size: %zu, expected: 1.\n",
+			actual_size);
+		return ELIMIT;
+	}
+	
+	*protocol = buffer[0];
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Get Idle request to the HID device.
+ *
+ * @param[in] hid_dev HID device to send the request to.
+ * @param[out] duration Duration value (multiplicate by 4 to get real duration
+ *                      in miliseconds).
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from one of functions 
+ *         usb_pipe_start_session(), usb_pipe_end_session(),
+ *         usb_control_request_set().
+ */
+int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	usb_log_debug("Sending Get_Idle request to the device ("
+	    "iface: %d).\n", iface_no);
+	
+	uint16_t value = 0;
+	uint8_t buffer[1];
+	size_t actual_size = 0;
+	
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_IDLE, value, iface_no, buffer, 1, 
+	    &actual_size);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending output report to the keyboard: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+
+	if (sess_rc != EOK) {
+		usb_log_warning("Error closing session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+	
+	if (actual_size != 1) {
+		usb_log_warning("Wrong data size: %zu, expected: 1.\n",
+			actual_size);
+		return ELIMIT;
+	}
+	
+	*duration = buffer[0];
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @}
+ */
