Index: uspace/drv/usbhid/Makefile
===================================================================
--- uspace/drv/usbhid/Makefile	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/Makefile	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -47,4 +47,5 @@
 	mouse/mousedev.c \
 	lgtch-ultrax/lgtch-ultrax.c \
+	lgtch-ultrax/keymap.c \
 	$(STOLEN_LAYOUT_SOURCES)
 
Index: uspace/drv/usbhid/kbd/conv.c
===================================================================
--- uspace/drv/usbhid/kbd/conv.c	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/kbd/conv.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -99,5 +99,6 @@
 	[0x30] = KC_RBRACKET,
 	[0x31] = KC_BACKSLASH,
-	//[0x32] = KC_,	// TODO: HASH??? maybe some as 0x31 - backslash
+	//[0x32] = KC_,	// TODO: HASH??? maybe same as 0x31 - backslash
+	[0x32] = KC_BACKSLASH,
 	[0x33] = KC_SEMICOLON,
 	[0x34] = KC_QUOTE,  // same as APOSTROPHE? (')
Index: uspace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/kbd/kbddev.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -177,10 +177,10 @@
 /*----------------------------------------------------------------------------*/
 
-static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
-    uint8_t report_id, void *arg);
-
-static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = {
-	.keyboard = usb_kbd_process_keycodes
-};
+//static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
+//    uint8_t report_id, void *arg);
+
+//static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = {
+//	.keyboard = usb_kbd_process_keycodes
+//};
 
 /*----------------------------------------------------------------------------*/
@@ -203,27 +203,27 @@
 /*----------------------------------------------------------------------------*/
 /** Mapping of USB modifier key codes to generic modifier key codes. */
-static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
-	KC_LCTRL,         /* USB_HID_MOD_LCTRL */
-	KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
-	KC_LALT,          /* USB_HID_MOD_LALT */
-	0,                /* USB_HID_MOD_LGUI */
-	KC_RCTRL,         /* USB_HID_MOD_RCTRL */
-	KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
-	KC_RALT,          /* USB_HID_MOD_RALT */
-	0,                /* USB_HID_MOD_RGUI */
-};
-
-typedef enum usbhid_lock_code {
-	USB_KBD_LOCK_NUM = 0x53,
-	USB_KBD_LOCK_CAPS = 0x39,
-	USB_KBD_LOCK_SCROLL = 0x47,
-	USB_KBD_LOCK_COUNT = 3
-} usbhid_lock_code;
-
-static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = {
-	USB_KBD_LOCK_NUM,
-	USB_KBD_LOCK_CAPS,
-	USB_KBD_LOCK_SCROLL
-};
+//static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
+//	KC_LCTRL,         /* USB_HID_MOD_LCTRL */
+//	KC_LSHIFT,        /* USB_HID_MOD_LSHIFT */
+//	KC_LALT,          /* USB_HID_MOD_LALT */
+//	0,                /* USB_HID_MOD_LGUI */
+//	KC_RCTRL,         /* USB_HID_MOD_RCTRL */
+//	KC_RSHIFT,        /* USB_HID_MOD_RSHIFT */
+//	KC_RALT,          /* USB_HID_MOD_RALT */
+//	0,                /* USB_HID_MOD_RGUI */
+//};
+
+//typedef enum usbhid_lock_code {
+//	USB_KBD_LOCK_NUM = 0x53,
+//	USB_KBD_LOCK_CAPS = 0x39,
+//	USB_KBD_LOCK_SCROLL = 0x47,
+//	USB_KBD_LOCK_COUNT = 3
+//} usbhid_lock_code;
+
+//static const usbhid_lock_code usbhid_lock_codes[USB_KBD_LOCK_COUNT] = {
+//	USB_KBD_LOCK_NUM,
+//	USB_KBD_LOCK_CAPS,
+//	USB_KBD_LOCK_SCROLL
+//};
 
 /*----------------------------------------------------------------------------*/
@@ -299,32 +299,39 @@
 		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.\n");
-	
-	int rc = usb_hid_report_output_translate(hid_dev->parser, 
-	    kbd_dev->led_path, 
-	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    kbd_dev->output_buffer, 
-	    kbd_dev->output_size, 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->report, 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->report, field,
+		    kbd_dev->led_path, USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY 
+		    | USB_HID_PATH_COMPARE_END, USB_HID_REPORT_TYPE_OUTPUT);
+	}
+	
+	// TODO: what about the Report ID?
+	int rc = usb_hid_report_output_translate(hid_dev->report, 0,
+	    kbd_dev->output_buffer, kbd_dev->output_size);
 	
 	if (rc != EOK) {
@@ -485,5 +492,5 @@
  */
 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
-    usb_kbd_t *kbd_dev, const uint8_t *key_codes, size_t count)
+    usb_kbd_t *kbd_dev/*, const uint8_t *key_codes, size_t count*/)
 {
 	unsigned int key;
@@ -499,30 +506,27 @@
 	 */
 	i = 0;
-	while (i < count && key_codes[i] != ERROR_ROLLOVER) {
+	while (i < kbd_dev->key_count && kbd_dev->keys[i] != ERROR_ROLLOVER) {
 		++i;
 	}
-	if (i != count) {
+	if (i != kbd_dev->key_count) {
 		usb_log_debug("Phantom state occured.\n");
 		// phantom state, do nothing
 		return;
 	}
-	
-	/* TODO: quite dummy right now, think of better implementation */
-	assert(count == kbd_dev->key_count);
 	
 	/*
 	 * 1) Key releases
 	 */
-	for (j = 0; j < count; ++j) {
+	for (j = 0; j < kbd_dev->key_count; ++j) {
 		// try to find the old key in the new key list
 		i = 0;
 		while (i < kbd_dev->key_count
-		    && key_codes[i] != kbd_dev->keys[j]) {
+		    && kbd_dev->keys[i] != kbd_dev->keys_old[j]) {
 			++i;
 		}
 		
-		if (i == count) {
+		if (i == kbd_dev->key_count) {
 			// not found, i.e. the key was released
-			key = usbhid_parse_scancode(kbd_dev->keys[j]);
+			key = usbhid_parse_scancode(kbd_dev->keys_old[j]);
 			if (!usb_kbd_is_lock(key)) {
 				usb_kbd_repeat_stop(kbd_dev, key);
@@ -541,15 +545,15 @@
 		// try to find the new key in the old key list
 		j = 0;
-		while (j < count && kbd_dev->keys[j] != key_codes[i]) { 
+		while (j < kbd_dev->key_count 
+		    && kbd_dev->keys_old[j] != kbd_dev->keys[i]) { 
 			++j;
 		}
 		
-		if (j == count) {
+		if (j == kbd_dev->key_count) {
 			// not found, i.e. new key pressed
-			key = usbhid_parse_scancode(key_codes[i]);
+			key = usbhid_parse_scancode(kbd_dev->keys[i]);
 			usb_log_debug2("Key pressed: %d (keycode: %d)\n", key,
-			    key_codes[i]);
-			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, 
-			    key);
+			    kbd_dev->keys[i]);
+			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
 			if (!usb_kbd_is_lock(key)) {
 				usb_kbd_repeat_start(kbd_dev, key);
@@ -560,8 +564,24 @@
 	}
 	
-	memcpy(kbd_dev->keys, key_codes, count);
-
-	usb_log_debug("New stored keycodes: %s\n", 
-	    usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0));
+//	usb_log_debug("Old keys: ");
+//	for (i = 0; i < kbd_dev->key_count; ++i) {
+//		usb_log_debug("%d ", kbd_dev->keys_old[i]);
+//	}
+//	usb_log_debug("\n");
+	
+	
+//	usb_log_debug("New keys: ");
+//	for (i = 0; i < kbd_dev->key_count; ++i) {
+//		usb_log_debug("%d ", kbd_dev->keys[i]);
+//	}
+//	usb_log_debug("\n");
+	
+	memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
+	
+	usb_log_debug2("New stored keys: ");
+	for (i = 0; i < kbd_dev->key_count; ++i) {
+		usb_log_debug2("%d ", kbd_dev->keys_old[i]);
+	}
+	usb_log_debug2("\n");
 }
 
@@ -585,34 +605,34 @@
  * @sa usb_kbd_check_key_changes(), usb_kbd_check_modifier_changes()
  */
-static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
-    uint8_t report_id, void *arg)
-{
-	if (arg == NULL) {
-		usb_log_warning("Missing argument in callback "
-		    "usbhid_process_keycodes().\n");
-		return;
-	}
-	
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
-	
-	if (hid_dev->data == NULL) {
-		usb_log_warning("Missing KBD device structure in callback.\n");
-		return;
-	}
-	
-	usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
-
-	usb_log_debug("Got keys from parser (report id: %u): %s\n", 
-	    report_id, usb_debug_str_buffer(key_codes, count, 0));
-	
-	if (count != kbd_dev->key_count) {
-		usb_log_warning("Number of received keycodes (%zu) differs from"
-		    " expected (%zu).\n", count, kbd_dev->key_count);
-		return;
-	}
-	
-	///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count);
-	usb_kbd_check_key_changes(hid_dev, kbd_dev, key_codes, count);
-}
+//static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
+//    uint8_t report_id, void *arg)
+//{
+//	if (arg == NULL) {
+//		usb_log_warning("Missing argument in callback "
+//		    "usbhid_process_keycodes().\n");
+//		return;
+//	}
+	
+//	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
+	
+//	if (hid_dev->data == NULL) {
+//		usb_log_warning("Missing KBD device structure in callback.\n");
+//		return;
+//	}
+	
+//	usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
+
+//	usb_log_debug("Got keys from parser (report id: %u): %s\n", 
+//	    report_id, usb_debug_str_buffer(key_codes, count, 0));
+	
+//	if (count != kbd_dev->key_count) {
+//		usb_log_warning("Number of received keycodes (%zu) differs from"
+//		    " expected (%zu).\n", count, kbd_dev->key_count);
+//		return;
+//	}
+	
+//	///usb_kbd_check_modifier_changes(kbd_dev, key_codes, count);
+//	usb_kbd_check_key_changes(hid_dev, kbd_dev, key_codes, count);
+//}
 
 /*----------------------------------------------------------------------------*/
@@ -638,5 +658,9 @@
                                  uint8_t *buffer, size_t actual_size)
 {
-	assert(hid_dev->parser != NULL);
+	assert(hid_dev->report != NULL);
+	assert(hid_dev != NULL);
+	assert(hid_dev->data != NULL);
+	
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)hid_dev->data;
 
 	usb_log_debug("Calling usb_hid_parse_report() with "
@@ -648,16 +672,59 @@
 	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, path, 
+
+	uint8_t report_id;
+	int rc = usb_hid_parse_report(hid_dev->report, buffer, actual_size, 
+	    &report_id);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error in usb_hid_parse_report():"
+		    "%s\n", str_error(rc));
+	}
+	
+	usb_hid_report_path_set_report_id (path, report_id);
+	
+	// fill in the currently pressed keys
+	
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, 
 	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    &usb_kbd_parser_callbacks, hid_dev);
-
+	    USB_HID_REPORT_TYPE_INPUT);
+	unsigned i = 0;
+	
+	while (field != NULL) {
+		usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
+		    field, field->value, field->usage);
+		
+		assert(i < kbd_dev->key_count);
+//		if (i == kbd_dev->key_count) {
+//			break;
+//		}
+		
+		// save the key usage
+		/* TODO: maybe it's not good to save value, nor usage
+		 *       as the value may be e.g. 1 for LEDs and usage may be
+		 *       value of the LED. On the other hand, in case of normal
+		 *       keys, the usage is more important and we must check
+		 *       that. One possible solution: distinguish between those
+		 *       two parts of the Report somehow.
+		 */
+		if (field->value != 0) {
+			kbd_dev->keys[i] = field->usage;
+		}
+		else {
+			kbd_dev->keys[i] = 0;
+		}
+		usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
+		
+		++i;
+		field = usb_hid_report_get_sibling(hid_dev->report, field, path, 
+		    USB_HID_PATH_COMPARE_END 
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}
+	
 	usb_hid_report_path_free(path);
 	
-	if (rc != EOK) {
-		usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
-		    "%s\n", str_error(rc));
-	}
+	usb_kbd_check_key_changes(hid_dev, kbd_dev);
 }
 
@@ -747,5 +814,5 @@
 	
 	kbd_dev->key_count = usb_hid_report_input_length(
-	    hid_dev->parser, path, 
+	    hid_dev->report, path, 
 	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
 	usb_hid_report_path_free(path);
@@ -753,5 +820,5 @@
 	usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
 	
-	kbd_dev->keys = (uint8_t *)calloc(kbd_dev->key_count, sizeof(uint8_t));
+	kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
 	
 	if (kbd_dev->keys == NULL) {
@@ -761,15 +828,24 @@
 	}
 	
+	kbd_dev->keys_old = 
+		(int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
+	
+	if (kbd_dev->keys_old == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev->keys);
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
 	/*
 	 * Output report
 	 */
 	kbd_dev->output_size = 0;
-	kbd_dev->output_buffer = usb_hid_report_output(hid_dev->parser, 
-	    &kbd_dev->output_size);
-	if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
+	kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report, 
+	    &kbd_dev->output_size, 0);
+	if (kbd_dev->output_buffer == NULL) {
 		usb_log_warning("Error creating output report buffer.\n");
 		free(kbd_dev->keys);
-		free(kbd_dev);
-		return ENOMEM;
+		return ENOMEM;  /* TODO: other error code */
 	}
 	
@@ -780,5 +856,5 @@
 	    kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
 	
-	kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->parser, 
+	kbd_dev->led_output_size = usb_hid_report_output_size(hid_dev->report, 
 	    kbd_dev->led_path, 
 	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
@@ -908,6 +984,23 @@
 	}
 	
-	// free the output buffer
-	usb_hid_report_output_free((*kbd_dev)->output_buffer);
+	// free all buffers
+	if ((*kbd_dev)->keys != NULL) {
+		free((*kbd_dev)->keys);
+	}
+	if ((*kbd_dev)->keys_old != NULL) {
+		free((*kbd_dev)->keys_old);
+	}
+	if ((*kbd_dev)->led_data != NULL) {
+		free((*kbd_dev)->led_data);
+	}
+	if ((*kbd_dev)->output_buffer != NULL) {
+		free((*kbd_dev)->output_buffer);
+	}
+	if ((*kbd_dev)->led_path != NULL) {
+		usb_hid_report_path_free((*kbd_dev)->led_path);
+	}
+	if ((*kbd_dev)->output_buffer != NULL) {
+		usb_hid_report_output_free((*kbd_dev)->output_buffer);
+	}
 
 	free(*kbd_dev);
@@ -929,4 +1022,5 @@
 		} else {
 			usb_kbd_free(&kbd_dev);
+			hid_dev->data = NULL;
 		}
 	}
@@ -937,5 +1031,5 @@
 int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
 {
-	int rc = usb_hid_parse_report_descriptor(hid_dev->parser, 
+	int rc = usb_hid_parse_report_descriptor(hid_dev->report, 
 	    USB_KBD_BOOT_REPORT_DESCRIPTOR, 
 	    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
Index: uspace/drv/usbhid/kbd/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.h	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/kbd/kbddev.h	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -65,6 +65,8 @@
  */
 typedef struct usb_kbd_t {
+	/** Previously pressed keys (not translated to key codes). */
+	int32_t *keys_old;
 	/** Currently pressed keys (not translated to key codes). */
-	uint8_t *keys;
+	int32_t *keys;
 	/** Count of stored keys (i.e. number of keys in the report). */
 	size_t key_count;
Index: uspace/drv/usbhid/lgtch-ultrax/keymap.c
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/keymap.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
+++ uspace/drv/usbhid/lgtch-ultrax/keymap.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -0,0 +1,101 @@
+/*
+ * 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
+ * UUSB multimedia key to keycode mapping.
+ */
+
+#include <io/keycode.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include "keymap.h"
+
+/**
+ * Mapping between USB HID multimedia usages (from HID Usage Tables) and 
+ * corresponding HelenOS key codes.
+ *
+ * Currently only Usages used by Logitech UltraX keyboard are present. All other
+ * should result in 0.
+ */
+static int usb_hid_keymap_consumer[0x29c] = {
+	[0xf] = KC_F1, /* Just for testing purposes */
+	[0x5] = KC_F1, /* Just for testing purposes */
+	[0x8] = KC_F3, /* Just for testing purposes */
+	[0x6] = KC_F4, /* Just for testing purposes */
+	[0x7] = KC_F5, /* Just for testing purposes */
+	[0xc] = KC_F6, /* Just for testing purposes */
+	
+	[0xb5] = 0,  /* Scan Next Track */
+	[0xb6] = 0,  /* Scan Previous Track */
+	[0xb7] = 0,  /* Stop */
+	[0xb8] = 0,  /* Eject */
+	[0xcd] = KC_F2,  /* Play/Pause */
+	[0xe2] = KC_F3,  /* Mute */
+	[0xe9] = KC_F5,  /* Volume Increment */
+	[0xea] = KC_F4,  /* Volume Decrement */
+	[0x183] = 0, /* AL Consumer Control Configuration */
+	[0x18a] = 0, /* AL Email Reader */
+	[0x192] = 0, /* AL Calculator */
+	[0x221] = 0, /* AC Search */
+	[0x223] = 0, /* AC Home */
+	[0x224] = 0, /* AC Back */
+	[0x225] = 0, /* AC Forward */
+	[0x226] = 0, /* AC Stop */
+	[0x227] = KC_F1, /* AC Refresh */
+	[0x22a] = KC_F6  /* AC Bookmarks */
+};
+
+/**
+ * Translates USB HID Usages from the Consumer Page into HelenOS keycodes.
+ *
+ * @param usage USB HID Consumer Page Usage number.
+ * 
+ * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
+ */
+unsigned int usb_lgtch_map_usage(int usage)
+{
+	unsigned int key;
+	int *map = usb_hid_keymap_consumer;
+	size_t map_length = sizeof(usb_hid_keymap_consumer) / sizeof(int);
+
+	if ((usage < 0) || ((size_t)usage >= map_length))
+		return -1;
+
+	/*! @todo What if the usage is not in the table? */
+	key = map[usage];
+	
+	return key;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/lgtch-ultrax/keymap.h
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/keymap.h	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
+++ uspace/drv/usbhid/lgtch-ultrax/keymap.h	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -0,0 +1,45 @@
+/*
+ * 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
+ * USB multimedia key to keycode mapping.
+ */
+
+#ifndef USB_HID_LGTCH_ULTRAX_KEYMAP_H_
+#define USB_HID_LGTCH_ULTRAX_KEYMAP_H_
+
+unsigned int usb_lgtch_map_usage(int usage);
+
+#endif /* USB_HID_LGTCH_ULTRAX_KEYMAP_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -38,30 +38,300 @@
 #include "lgtch-ultrax.h"
 #include "../usbhid.h"
+#include "keymap.h"
 
 #include <usb/classes/hidparser.h>
 #include <usb/debug.h>
+#include <usb/classes/hidut.h>
+
 #include <errno.h>
 #include <str_error.h>
 
+#include <ipc/kbd.h>
+#include <io/console.h>
+
 #define NAME "lgtch-ultrax"
 
-/*----------------------------------------------------------------------------*/
-
-static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
-    uint8_t report_id, void *arg);
-
-static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
-	.keyboard = usb_lgtch_process_keycodes
+typedef enum usb_lgtch_flags {
+	USB_LGTCH_STATUS_UNINITIALIZED = 0,
+	USB_LGTCH_STATUS_INITIALIZED = 1,
+	USB_LGTCH_STATUS_TO_DESTROY = -1
+} usb_lgtch_flags;
+
+
+/*----------------------------------------------------------------------------*/
+/** 
+ * Default handler for IPC methods not handled by DDF.
+ *
+ * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
+ * assumes the caller is the console and thus it stores IPC phone to it for 
+ * later use by the driver to notify about key events.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+static void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	usb_log_debug(NAME " default_connection_handler()\n");
+	
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	if (hid_dev == NULL || hid_dev->data == NULL) {
+		async_answer_0(icallid, EINVAL);
+		return;
+	}
+	
+	assert(hid_dev != NULL);
+	assert(hid_dev->data != NULL);
+	usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
+
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (lgtch_dev->console_phone != -1) {
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		lgtch_dev->console_phone = callback;
+		usb_log_debug(NAME " Saved phone to console: %d\n", callback);
+		async_answer_0(icallid, EOK);
+		return;
+	}
+	
+	async_answer_0(icallid, EINVAL);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static ddf_dev_ops_t lgtch_ultrax_ops = {
+	.default_handler = default_connection_handler
 };
 
 /*----------------------------------------------------------------------------*/
 
-static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
-    uint8_t report_id, void *arg)
-{
-	// TODO: checks
-	
-	usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n", 
-	    report_id, usb_debug_str_buffer(key_codes, count, 0));
+//static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
+//    uint8_t report_id, void *arg);
+
+//static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
+//	.keyboard = usb_lgtch_process_keycodes
+//};
+
+///*----------------------------------------------------------------------------*/
+
+//static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
+//    uint8_t report_id, void *arg)
+//{
+//	// TODO: checks
+	
+//	usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n", 
+//	    report_id, usb_debug_str_buffer(key_codes, count, 0));
+//}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Processes key events.
+ *
+ * @note This function was copied from AT keyboard driver and modified to suit
+ *       USB keyboard.
+ *
+ * @note Lock keys are not sent to the console, as they are completely handled
+ *       in the driver. It may, however, be required later that the driver
+ *       sends also these keys to application (otherwise it cannot use those
+ *       keys at all).
+ * 
+ * @param hid_dev 
+ * @param lgtch_dev 
+ * @param type Type of the event (press / release). Recognized values: 
+ *             KEY_PRESS, KEY_RELEASE
+ * @param key Key code of the key according to HID Usage Tables.
+ */
+static void usb_lgtch_push_ev(usb_hid_dev_t *hid_dev, int type, 
+    unsigned int key)
+{
+	assert(hid_dev != NULL);
+	assert(hid_dev->data != NULL);
+	
+	usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)hid_dev->data;
+	
+	console_event_t ev;
+	
+	ev.type = type;
+	ev.key = key;
+	ev.mods = 0;
+
+	ev.c = 0;
+
+	usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
+	if (lgtch_dev->console_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
+	
+	async_msg_4(lgtch_dev->console_phone, KBD_EVENT, ev.type, ev.key, 
+	    ev.mods, ev.c);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_lgtch_free(usb_lgtch_ultrax_t **lgtch_dev)
+{
+	if (lgtch_dev == NULL || *lgtch_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_hangup((*lgtch_dev)->console_phone);
+	
+//	if ((*lgtch_dev)->repeat_mtx != NULL) {
+//		/* TODO: replace by some check and wait */
+//		assert(!fibril_mutex_is_locked((*lgtch_dev)->repeat_mtx));
+//		free((*lgtch_dev)->repeat_mtx);
+//	}
+	
+	// free all buffers
+	if ((*lgtch_dev)->keys != NULL) {
+		free((*lgtch_dev)->keys);
+	}
+	if ((*lgtch_dev)->keys_old != NULL) {
+		free((*lgtch_dev)->keys_old);
+	}
+
+	free(*lgtch_dev);
+	*lgtch_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_lgtch_init(struct usb_hid_dev *hid_dev)
+{
+	if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
+		return EINVAL; /*! @todo Other return code? */
+	}
+	
+	usb_log_debug(NAME " Initializing HID/lgtch_ultrax structure...\n");
+	
+	usb_lgtch_ultrax_t *lgtch_dev = (usb_lgtch_ultrax_t *)malloc(
+	    sizeof(usb_lgtch_ultrax_t));
+	if (lgtch_dev == NULL) {
+		return ENOMEM;
+	}
+	
+	lgtch_dev->console_phone = -1;
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
+	
+	usb_hid_report_path_set_report_id(path, 1);
+	
+	lgtch_dev->key_count = usb_hid_report_input_length(
+	    hid_dev->report, path, 
+	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
+	usb_hid_report_path_free(path);
+	
+	usb_log_debug(NAME " Size of the input report: %zu\n", 
+	    lgtch_dev->key_count);
+	
+	lgtch_dev->keys = (int32_t *)calloc(lgtch_dev->key_count, 
+	    sizeof(int32_t));
+	
+	if (lgtch_dev->keys == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(lgtch_dev);
+		return ENOMEM;
+	}
+	
+	lgtch_dev->keys_old = 
+		(int32_t *)calloc(lgtch_dev->key_count, sizeof(int32_t));
+	
+	if (lgtch_dev->keys_old == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(lgtch_dev->keys);
+		free(lgtch_dev);
+		return ENOMEM;
+	}
+	
+	/*! @todo Autorepeat */
+	
+	// save the KBD device structure into the HID device structure
+	hid_dev->data = lgtch_dev;
+	
+	/* Create the function exposed under /dev/devices. */
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
+	usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
+	
+	/*
+	 * Store the initialized HID device and HID ops
+	 * to the DDF function.
+	 */
+	fun->ops = &lgtch_ultrax_ops;
+	fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
+	
+	/*
+	 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
+	 *    do nej.
+	 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 
+	 *    vyplnenu strukturu usbhid_iface_t.
+	 * 3) klientska aplikacia - musi si rucne vytvorit telefon
+	 *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 
+	 *    k tej fcii.
+	 *    pouzit usb/classes/hid/iface.h - prvy int je telefon
+	 */
+
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(fun);
+		usb_lgtch_free(&lgtch_dev);
+		return rc;
+	}
+	
+	rc = ddf_fun_add_to_class(fun, "keyboard");
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class 'keyboard': %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(fun);
+		usb_lgtch_free(&lgtch_dev);
+		return rc;
+	}
+	
+	usb_log_debug(NAME " HID/lgtch_ultrax structure initialized.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_lgtch_deinit(struct usb_hid_dev *hid_dev)
+{
+	if (hid_dev == NULL) {
+		return;
+	}
+	
+	if (hid_dev->data != NULL) {
+		usb_lgtch_ultrax_t *lgtch_dev = 
+		    (usb_lgtch_ultrax_t *)hid_dev->data;
+//		if (usb_kbd_is_initialized(kbd_dev)) {
+//			usb_kbd_mark_unusable(kbd_dev);
+//		} else {
+			usb_lgtch_free(&lgtch_dev);
+			hid_dev->data = NULL;
+//		}
+	}
 }
 
@@ -81,15 +351,38 @@
 	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, 1);
-	
-	int rc = usb_hid_parse_report(hid_dev->parser, buffer,
-	    buffer_size, path, 
-	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    &usb_lgtch_parser_callbacks, hid_dev);
+
+	uint8_t report_id;
+	
+	int rc = usb_hid_parse_report(hid_dev->report, 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->report, NULL, path, USB_HID_PATH_COMPARE_END 
+	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    USB_HID_REPORT_TYPE_INPUT);
+	
+	unsigned int key;
+	
+	/*! @todo Is this iterating OK if done multiple times? 
+	 *  @todo The parsing is not OK
+	 */
+	while (field != NULL) {
+		usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", field->value, 
+		    field->usage);
+		
+		key = usb_lgtch_map_usage(field->usage);
+		usb_lgtch_push_ev(hid_dev, KEY_PRESS, key);
+		
+		field = usb_hid_report_get_sibling(
+		    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}	
 
 	usb_hid_report_path_free(path);
 	
 	if (rc != EOK) {
-		usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
+		usb_log_warning(NAME "Error in usb_hid_boot_keyboard_input_report():"
 		    "%s\n", str_error(rc));
 	}
Index: uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -40,13 +40,49 @@
 
 struct usb_hid_dev;
-//struct usb_hid_subdriver_mapping;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * USB/HID keyboard device type.
+ *
+ * Holds a reference to generic USB/HID device structure and keyboard-specific
+ * data, such as currently pressed keys, modifiers and lock keys.
+ *
+ * Also holds a IPC phone to the console (since there is now no other way to 
+ * communicate with it).
+ *
+ * @note Storing active lock keys in this structure results in their setting
+ *       being device-specific.
+ */
+typedef struct usb_lgtch_ultrax_t {
+	/** Previously pressed keys (not translated to key codes). */
+	int32_t *keys_old;
+	/** Currently pressed keys (not translated to key codes). */
+	int32_t *keys;
+	/** Count of stored keys (i.e. number of keys in the report). */
+	size_t key_count;
+	
+	/** IPC phone to the console device (for sending key events). */
+	int console_phone;
+
+	/** Information for auto-repeat of keys. */
+//	usb_kbd_repeat_t repeat;
+	
+	/** Mutex for accessing the information about auto-repeat. */
+//	fibril_mutex_t *repeat_mtx;
+
+	/** State of the structure (for checking before use). 
+	 * 
+	 * 0 - not initialized
+	 * 1 - initialized
+	 * -1 - ready for destroying
+	 */
+	int initialized;
+} usb_lgtch_ultrax_t;
 
 /*----------------------------------------------------------------------------*/
 
-//extern struct usb_hid_subdriver_mapping usb_lgtch_mapping;
+int usb_lgtch_init(struct usb_hid_dev *hid_dev);
 
-/*----------------------------------------------------------------------------*/
-
-//int usb_lgtch_init(struct usb_hid_dev *hid_dev);
+void usb_lgtch_deinit(struct usb_hid_dev *hid_dev);
 
 bool usb_lgtch_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/main.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -114,4 +114,15 @@
 	hid_fun->ops = &hid_dev->ops;
 	hid_fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
+	
+	/*
+	 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
+	 *    do nej.
+	 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 
+	 *    vyplnenu strukturu usbhid_iface_t.
+	 * 3) klientska aplikacia - musi si rucne vytvorit telefon
+	 *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 
+	 *    k tej fcii.
+	 *    pouzit usb/classes/hid/iface.h - prvy int je telefon
+	 */
 
 	rc = ddf_fun_bind(hid_fun);
Index: uspace/drv/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.c	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/mouse/mousedev.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -296,5 +296,5 @@
 int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
 {
-	int rc = usb_hid_parse_report_descriptor(hid_dev->parser, 
+	int rc = usb_hid_parse_report_descriptor(hid_dev->report, 
 	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR, 
 	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
Index: uspace/drv/usbhid/subdrivers.c
===================================================================
--- uspace/drv/usbhid/subdrivers.c	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/subdrivers.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -55,6 +55,6 @@
 		USB_HID_PATH_COMPARE_END 
 		| USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
-		0,
-		0,
+		-1,
+		-1,
 		{
 			.init = usb_kbd_init,
@@ -73,11 +73,11 @@
 		0xc30e,
 		{
-			.init = NULL,
-			.deinit = NULL,
+			.init = usb_lgtch_init,
+			.deinit = usb_lgtch_deinit,
 			.poll = usb_lgtch_polling_callback,
 			.poll_end = NULL
 		}
 	},
-	{NULL, -1, 0, 0, 0, {NULL, NULL, NULL, NULL}}
+	{NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL}}
 };
 
Index: uspace/drv/usbhid/subdrivers.h
===================================================================
--- uspace/drv/usbhid/subdrivers.h	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/subdrivers.h	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -56,6 +56,6 @@
 	int report_id;
 	int compare;
-	uint16_t vendor_id;
-	uint16_t product_id;
+	int vendor_id;
+	int product_id;
 	usb_hid_subdriver_t subdriver;
 } usb_hid_subdriver_mapping_t;
Index: uspace/drv/usbhid/usbhid.c
===================================================================
--- uspace/drv/usbhid/usbhid.c	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/usbhid.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -158,5 +158,11 @@
     const usb_hid_subdriver_mapping_t *mapping)
 {
-	return false;
+	assert(hid_dev != NULL);
+	assert(hid_dev->usb_dev != NULL);
+	
+	return (hid_dev->usb_dev->descriptors.device.vendor_id 
+	    == mapping->vendor_id
+	    && hid_dev->usb_dev->descriptors.device.product_id 
+	    == mapping->product_id);
 }
 
@@ -192,8 +198,8 @@
 	}
 	
-	assert(hid_dev->parser != NULL);
+	assert(hid_dev->report != NULL);
 	
 	usb_log_debug("Compare flags: %d\n", mapping->compare);
-	size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path, 
+	size_t size = usb_hid_report_input_length(hid_dev->report, usage_path, 
 	    mapping->compare);
 	usb_log_debug("Size of the input report: %zuB\n", size);
@@ -251,13 +257,13 @@
 	while (count < USB_HID_MAX_SUBDRIVERS &&
 	    (mapping->usage_path != NULL
-	    || mapping->vendor_id != 0 || mapping->product_id != 0)) {
+	    || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
 		// check the vendor & product ID
-		if (mapping->vendor_id != 0 && mapping->product_id == 0) {
-			usb_log_warning("Missing Product ID for Vendor ID %u\n",
+		if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
+			usb_log_warning("Missing Product ID for Vendor ID %d\n",
 			    mapping->vendor_id);
 			return EINVAL;
 		}
-		if (mapping->product_id != 0 && mapping->vendor_id == 0) {
-			usb_log_warning("Missing Vendor ID for Product ID %u\n",
+		if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
+			usb_log_warning("Missing Vendor ID for Product ID %d\n",
 			    mapping->product_id);
 			return EINVAL;
@@ -267,6 +273,6 @@
 		matched = false;
 		
-		if (mapping->vendor_id != 0) {
-			assert(mapping->product_id != 0);
+		if (mapping->vendor_id >= 0) {
+			assert(mapping->product_id >= 0);
 			usb_log_debug("Comparing device against vendor ID %u"
 			    " and product ID %u.\n", mapping->vendor_id,
@@ -341,7 +347,7 @@
 	}
 	
-	hid_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
-	    usb_hid_report_parser_t)));
-	if (hid_dev->parser == NULL) {
+	hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
+	    usb_hid_report_t)));
+	if (hid_dev->report == NULL) {
 		usb_log_fatal("No memory!\n");
 		free(hid_dev);
@@ -382,16 +388,8 @@
 		return rc;
 	}
-	
-	/* Initialize the report parser. */
-	rc = usb_hid_parser_init(hid_dev->parser);
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize report parser.\n");
-		//usb_hid_free(&hid_dev);
-		return rc;
-	}
-	
+		
 	/* Get the report descriptor and parse it. */
 	rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 
-	    hid_dev->parser);
+	    hid_dev->report);
 	
 	bool fallback = false;
@@ -591,6 +589,6 @@
 
 	// destroy the parser
-	if ((*hid_dev)->parser != NULL) {
-		usb_hid_free_report_parser((*hid_dev)->parser);
+	if ((*hid_dev)->report != NULL) {
+		usb_hid_free_report((*hid_dev)->report);
 	}
 
Index: uspace/drv/usbhid/usbhid.h
===================================================================
--- uspace/drv/usbhid/usbhid.h	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbhid/usbhid.h	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -91,5 +91,5 @@
 	
 	/** HID Report parser. */
-	usb_hid_report_parser_t *parser;
+	usb_hid_report_t *report;
 	
 	/** Arbitrary data (e.g. a special structure for handling keyboard). */
Index: uspace/drv/usbkbd/kbddev.c
===================================================================
--- uspace/drv/usbkbd/kbddev.c	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbkbd/kbddev.c	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -128,7 +128,10 @@
         0x15, 0x00,  //   Logical Minimum (0),
         0x25, 0x01,  //   Logical Maximum (1),
+	//0x85, 0x00,  //   Report ID,
+	//0xA4,	     //   Push
         0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
-	0x95, 0x01,  //   Report Count (1),
-        0x75, 0x08,  //   Report Size (8),
+	//0xB4,	     //   Pop
+        0x75, 0x08,  //   Report Size (1),
+        0x95, 0x01,  //   Report Count (8),       
         0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
         0x95, 0x05,  //   Report Count (5),
@@ -268,5 +271,5 @@
 		return;
 	}
-	
+
 	unsigned i = 0;
 	
@@ -290,10 +293,10 @@
 	
 	usb_log_debug("Creating output report.\n");
-	
-	int rc = usb_hid_report_output_translate(kbd_dev->parser, 
-	    kbd_dev->led_path, 
-	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    kbd_dev->output_buffer, 
-	    kbd_dev->output_size, kbd_dev->led_data, kbd_dev->led_output_size);
+
+	usb_hid_report_output_set_data(kbd_dev->parser, kbd_dev->led_path, 
+	                               USB_HID_PATH_COMPARE_END , kbd_dev->led_data, 
+	                               kbd_dev->led_output_size);
+	int rc = usb_hid_report_output_translate(kbd_dev->parser, 0,
+	    kbd_dev->output_buffer, kbd_dev->output_size);
 	
 	if (rc != EOK) {
@@ -563,6 +566,6 @@
 	assert(kbd_dev != NULL);
 
-	usb_log_debug("Got keys from parser (report id: %u): %s\n", 
-	    report_id, usb_debug_str_buffer(key_codes, count, 0));
+	usb_log_debug("Got keys from parser (report id: %d): %s\n", report_id, 
+	    usb_debug_str_buffer(key_codes, count, 0));
 	
 	if (count != kbd_dev->key_count) {
@@ -614,10 +617,8 @@
 	usb_hid_report_path_t *path = usb_hid_report_path();
 	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(kbd_dev->parser, buffer,
-	    actual_size, path, 
-	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    callbacks, kbd_dev);
+
+	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);
 
 	usb_hid_report_path_free (path);
@@ -663,6 +664,6 @@
 	memset(kbd_dev, 0, sizeof(usb_kbd_t));
 	
-	kbd_dev->parser = (usb_hid_report_parser_t *)(malloc(sizeof(
-	    usb_hid_report_parser_t)));
+	kbd_dev->parser = (usb_hid_report_t *)(malloc(sizeof(
+	    usb_hid_report_t)));
 	if (kbd_dev->parser == NULL) {
 		usb_log_fatal("No memory!\n");
@@ -732,9 +733,9 @@
 	
 	/* Initialize the report parser. */
-	rc = usb_hid_parser_init(kbd_dev->parser);
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize report parser.\n");
-		return rc;
-	}
+	//rc = usb_hid_parser_init(kbd_dev->parser);
+	//if (rc != EOK) {
+	//	usb_log_error("Failed to initialize report parser.\n");
+	//	return rc;
+	//}
 	
 	/* Get the report descriptor and parse it. */
@@ -771,6 +772,5 @@
 	
 	kbd_dev->key_count = usb_hid_report_input_length(
-	    kbd_dev->parser, path, 
-	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY);
+	    kbd_dev->parser, path, USB_HID_PATH_COMPARE_END);
 	usb_hid_report_path_free (path);
 	
@@ -789,6 +789,6 @@
 	kbd_dev->output_size = 0;
 	kbd_dev->output_buffer = usb_hid_report_output(kbd_dev->parser, 
-	    &kbd_dev->output_size);
-	if (kbd_dev->output_buffer == NULL && kbd_dev->output_size != 0) {
+	    &kbd_dev->output_size, 0x00);
+	if (kbd_dev->output_buffer == NULL) {
 		usb_log_warning("Error creating output report buffer.\n");
 		free(kbd_dev->keys);
@@ -801,4 +801,5 @@
 	usb_hid_report_path_append_item(
 	    kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
+	usb_hid_report_path_set_report_id(kbd_dev->led_path, 0x00);
 	
 	kbd_dev->led_output_size = usb_hid_report_output_size(kbd_dev->parser, 
@@ -849,5 +850,5 @@
 	 * Set Idle rate
 	 */
-	usb_kbd_set_led(kbd_dev);
+	usb_kbd_set_led(kbd_dev);	
 	
 	usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe, 
@@ -934,5 +935,5 @@
 	// destroy the parser
 	if ((*kbd_dev)->parser != NULL) {
-		usb_hid_free_report_parser((*kbd_dev)->parser);
+		usb_hid_free_report((*kbd_dev)->parser);
 	}
 	
Index: uspace/drv/usbkbd/kbddev.h
===================================================================
--- uspace/drv/usbkbd/kbddev.h	(revision 152ec79b799dbc6398f151fbbf725964b8fe5205)
+++ uspace/drv/usbkbd/kbddev.h	(revision 9e929a0748e299f8c8c64707c8c35a05fba53138)
@@ -106,5 +106,5 @@
 
 	/** HID Report parser. */
-	usb_hid_report_parser_t *parser;
+	usb_hid_report_t *parser;
 	
 	/** State of the structure (for checking before use). 
