Index: uspace/app/mkbd/Makefile
===================================================================
--- uspace/app/mkbd/Makefile	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/app/mkbd/Makefile	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -31,11 +31,13 @@
 
 LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
 	$(LIBUSBDEV_PREFIX)/libusbdev.a \
 	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
+	$(LIBDRV_PREFIX)/libdrv.a 
 EXTRA_CFLAGS = \
 	-I$(LIBUSB_PREFIX)/include \
 	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
+	-I$(LIBDRV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include 
 
 SOURCES = \
Index: uspace/app/mkbd/main.c
===================================================================
--- uspace/app/mkbd/main.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/app/mkbd/main.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -45,6 +45,14 @@
 #include <devmap.h>
 #include <usb/dev/hub.h>
-#include <usb/hc.h>
+//#include <usb/host.h>
+//#include <usb/driver.h>
+#include <usb/hid/iface.h>
 #include <usb/dev/pipes.h>
+#include <async.h>
+#include <usb/hid/usages/core.h>
+#include <usb/hid/hidparser.h>
+#include <usb/hid/hiddescriptor.h>
+#include <usb/hid/usages/consumer.h>
+#include <assert.h>
 
 #define NAME "mkbd"
@@ -52,156 +60,129 @@
 static int dev_phone = -1;
 
-//static void print_found_hc(size_t class_index, const char *path)
-//{
-//	// printf(NAME ": host controller %zu is `%s'.\n", class_index, path);
-//	printf("Bus %02zu: %s\n", class_index, path);
-//}
-//static void print_found_dev(usb_address_t addr, const char *path)
-//{
-//	// printf(NAME ":     device with address %d is `%s'.\n", addr, path);
-//	printf("  Device %02d: %s\n", addr, path);
-//}
-
-//static void print_hc_devices(devman_handle_t hc_handle)
-//{
-//	int rc;
-//	usb_hc_connection_t conn;
-
-//	usb_hc_connection_initialize(&conn, hc_handle);
-//	rc = usb_hc_connection_open(&conn);
-//	if (rc != EOK) {
-//		printf(NAME ": failed to connect to HC: %s.\n",
-//		    str_error(rc));
-//		return;
-//	}
-//	usb_address_t addr;
-//	for (addr = 1; addr < 5; addr++) {
-//		devman_handle_t dev_handle;
-//		rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
-//		if (rc != EOK) {
-//			continue;
-//		}
-//		char path[MAX_PATH_LENGTH];
-//		rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
-//		if (rc != EOK) {
-//			continue;
-//		}
-//		print_found_dev(addr, path);
-//	}
-//	usb_hc_connection_close(&conn);
-//}
-
-static bool try_parse_class_and_address(const char *path,
-    devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
-{
-	size_t class_index;
-	size_t address;
-	int rc;
-	char *ptr;
-
-	rc = str_size_t(path, &ptr, 10, false, &class_index);
-	if (rc != EOK) {
-		return false;
-	}
-	if ((*ptr == ':') || (*ptr == '.')) {
-		ptr++;
-	} else {
-		return false;
-	}
-	rc = str_size_t(ptr, NULL, 10, true, &address);
-	if (rc != EOK) {
-		return false;
-	}
-	rc = usb_ddf_get_hc_handle_by_class(class_index, out_hc_handle);
-	if (rc != EOK) {
-		return false;
-	}
-	if (out_device_address != NULL) {
-		*out_device_address = (usb_address_t) address;
-	}
-	return true;
-}
-
-static bool resolve_hc_handle_and_dev_addr(const char *devpath,
-    devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
-{
-	int rc;
-
-	/* Hack for QEMU to save-up on typing ;-). */
-	if (str_cmp(devpath, "qemu") == 0) {
-		devpath = "/hw/pci0/00:01.2/uhci-rh/usb00_a1";
-	}
-
-	/* Hack for virtual keyboard. */
-	if (str_cmp(devpath, "virt") == 0) {
-		devpath = "/virt/usbhc/usb00_a1/usb00_a2";
-	}
-
-	if (try_parse_class_and_address(devpath,
-	    out_hc_handle, out_device_address)) {
-		return true;
-	}
-
-	char *path = str_dup(devpath);
+static int initialize_report_parser(int dev_phone, usb_hid_report_t **report)
+{
+	*report = (usb_hid_report_t *)malloc(sizeof(usb_hid_report_t));
+	if (*report == NULL) {
+		return ENOMEM;
+	}
+	
+	int rc = usb_hid_report_init(*report);
+	if (rc != EOK) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		printf("usb_hid_report_init() failed.\n");
+		return rc;
+	}
+	
+	// get the report descriptor length from the device
+	size_t report_desc_size;
+	rc = usbhid_dev_get_report_descriptor_length(
+	    dev_phone, &report_desc_size);
+	if (rc != EOK) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		printf("usbhid_dev_get_report_descriptor_length() failed.\n");
+		return rc;
+	}
+	
+	if (report_desc_size == 0) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		printf("usbhid_dev_get_report_descriptor_length() returned 0.\n");
+		return EINVAL;	// TODO: other error code?
+	}
+	
+	uint8_t *desc = (uint8_t *)malloc(report_desc_size);
+	if (desc == NULL) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		return ENOMEM;
+	}
+	
+	// get the report descriptor from the device
+	size_t actual_size;
+	rc = usbhid_dev_get_report_descriptor(dev_phone, desc, report_desc_size,
+	    &actual_size);
+	if (rc != EOK) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		free(desc);
+		printf("usbhid_dev_get_report_descriptor() failed.\n");
+		return rc;
+	}
+	
+	if (actual_size != report_desc_size) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		free(desc);
+		printf("usbhid_dev_get_report_descriptor() returned wrong size:"
+		    " %zu, expected: %zu.\n", actual_size, report_desc_size);
+		return EINVAL;	// TODO: other error code?
+	}
+	
+	// initialize the report parser
+	
+	rc = usb_hid_parse_report_descriptor(*report, desc, report_desc_size);
+	free(desc);
+	
+	if (rc != EOK) {
+		free(desc);
+		printf("usb_hid_parse_report_descriptor() failed.\n");
+		return rc;
+	}
+	
+	return EOK;
+}
+
+static void print_key(uint8_t *buffer, size_t size, usb_hid_report_t *report)
+{
+	assert(buffer != NULL);
+	assert(report != NULL);
+	
+	printf("Calling usb_hid_parse_report() with size %zu and "
+	    "buffer: \n", size);
+	for (size_t i = 0; i < size; ++i) {
+		printf(" %X ", buffer[i]);
+	}
+	printf("\n");
+	
+	uint8_t report_id;
+	int rc = usb_hid_parse_report(report, buffer, size, &report_id);
+	if (rc != EOK) {
+		printf("Error parsing report: %s\n", str_error(rc));
+		return;
+	}
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
 	if (path == NULL) {
-		return ENOMEM;
-	}
-
-	devman_handle_t hc = 0;
-	bool hc_found = false;
-	usb_address_t addr = 0;
-	bool addr_found = false;
-
-	/* Remove suffixes and hope that we will encounter device node. */
-	while (str_length(path) > 0) {
-		/* Get device handle first. */
-		devman_handle_t dev_handle;
-		rc = devman_device_get_handle(path, &dev_handle, 0);
-		if (rc != EOK) {
-			free(path);
-			return false;
+		return;
+	}
+	
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
+	
+	usb_hid_report_path_set_report_id(path, report_id);
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    report, NULL, path, USB_HID_PATH_COMPARE_END 
+	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    USB_HID_REPORT_TYPE_INPUT);
+	
+	while (field != NULL) {
+		if (field->value != 0) {
+			const char *key_str = 
+			    usbhid_multimedia_usage_to_str(field->usage);
+			printf("Pressed key: %s\n", key_str);
 		}
-
-		/* Try to find its host controller. */
-		if (!hc_found) {
-			rc = usb_hc_find(dev_handle, &hc);
-			if (rc == EOK) {
-				hc_found = true;
-			}
-		}
-		/* Try to get its address. */
-		if (!addr_found) {
-			addr = usb_hc_get_address_by_handle(dev_handle);
-			if (addr >= 0) {
-				addr_found = true;
-			}
-		}
-
-		/* Speed-up. */
-		if (hc_found && addr_found) {
-			break;
-		}
-
-		/* Remove the last suffix. */
-		char *slash_pos = str_rchr(path, '/');
-		if (slash_pos != NULL) {
-			*slash_pos = 0;
-		}
-	}
-
-	free(path);
-
-	if (hc_found && addr_found) {
-		if (out_hc_handle != NULL) {
-			*out_hc_handle = hc;
-		}
-		if (out_device_address != NULL) {
-			*out_device_address = addr;
-		}
-		return true;
-	} else {
-		return false;
-	}
-}
+		
+		field = usb_hid_report_get_sibling(
+		    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);
+}
+
+#define MAX_PATH_LENGTH 1024
 
 static void print_usage(char *app_name)
@@ -209,7 +190,7 @@
 #define _INDENT "      "
 
-	printf(NAME ": Print out what multimedia keys were pressed.\n\n");
-	printf("Usage: %s device\n", app_name);
-	printf(_INDENT "The device is a devman path to the device.\n");
+       printf(NAME ": Print out what multimedia keys were pressed.\n\n");
+       printf("Usage: %s device\n", app_name);
+       printf(_INDENT "The device is a devman path to the device.\n");
 
 #undef _OPTION
@@ -225,44 +206,22 @@
 	}
 	
-	char *devpath = argv[1];
-
-	/* The initialization is here only to make compiler happy. */
-	devman_handle_t hc_handle = 0;
-	usb_address_t dev_addr = 0;
-	bool found = resolve_hc_handle_and_dev_addr(devpath,
-	    &hc_handle, &dev_addr);
-	if (!found) {
-		fprintf(stderr, NAME ": device `%s' not found "
-		    "or not of USB kind. Exiting.\n", devpath);
-		return -1;
-	}
+	//char *devpath = argv[1];
+	const char *devpath = "/hw/pci0/00:06.0/ohci-rh/usb00_a2/HID1/hid";
 	
 	int rc;
-	usb_hc_connection_t conn;
-
-	usb_hc_connection_initialize(&conn, hc_handle);
-	rc = usb_hc_connection_open(&conn);
-	if (rc != EOK) {
-		printf(NAME ": failed to connect to HC: %s.\n",
+	
+	devman_handle_t dev_handle = 0;
+	rc = devman_device_get_handle(devpath, &dev_handle, 0);
+	if (rc != EOK) {
+		printf("Failed to get handle from devman: %s.\n",
 		    str_error(rc));
-		return -1;
-	}
-	usb_address_t addr = 0;
-
-	devman_handle_t dev_handle;
-	rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
-	if (rc != EOK) {
-		printf(NAME ": failed getting handle to the device: %s.\n",
-		       str_error(rc));
-		return -1;
-	}
-
-	usb_hc_connection_close(&conn);
+		return rc;
+	}
 	
 	rc = devman_device_connect(dev_handle, 0);
 	if (rc < 0) {
-		printf(NAME ": failed to connect to the device: %s.\n",
-		       str_error(rc));
-		return -1;
+		printf(NAME ": failed to connect to the device (handle %"
+		       PRIun "): %s.\n", dev_handle, str_error(rc));
+		return rc;
 	}
 	
@@ -270,24 +229,62 @@
 	printf("Got phone to the device: %d\n", dev_phone);
 	
-	
-//	size_t class_index = 0;
-//	size_t failed_attempts = 0;
-
-//	while (failed_attempts < MAX_FAILED_ATTEMPTS) {
-//		class_index++;
-//		devman_handle_t hc_handle = 0;
-//		int rc = usb_ddf_get_hc_handle_by_class(class_index, &hc_handle);
-//		if (rc != EOK) {
-//			failed_attempts++;
-//			continue;
-//		}
-//		char path[MAX_PATH_LENGTH];
-//		rc = devman_get_device_path(hc_handle, path, MAX_PATH_LENGTH);
-//		if (rc != EOK) {
-//			continue;
-//		}
-//		print_found_hc(class_index, path);
-//		print_hc_devices(hc_handle);
-//	}
+	char path[MAX_PATH_LENGTH];
+	rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
+	if (rc != EOK) {
+		return ENOMEM;
+	}
+	
+	printf("Device path: %s\n", path);
+	
+	
+	usb_hid_report_t *report = NULL;
+	rc = initialize_report_parser(dev_phone, &report);
+	if (rc != EOK) {
+		printf("Failed to initialize report parser: %s\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	assert(report != NULL);
+	
+	size_t size;
+	rc = usbhid_dev_get_event_length(dev_phone, &size);
+	if (rc != EOK) {
+		printf("Failed to get event length: %s.\n", str_error(rc));
+		return rc;
+	}
+	
+	printf("Event length: %zu\n", size);
+	uint8_t *event = (uint8_t *)malloc(size);
+	if (event == NULL) {
+		// hangup phone?
+		return ENOMEM;
+	}
+	
+	printf("Event length: %zu\n", size);
+	
+	size_t actual_size;
+	
+	while (1) {
+		// get event from the driver
+		printf("Getting event from the driver.\n");
+		
+		/** @todo Try blocking call. */
+		rc = usbhid_dev_get_event(dev_phone, event, size, &actual_size, 
+		    0);
+		if (rc != EOK) {
+			// hangup phone?
+			printf("Error in getting event from the HID driver:"
+			    "%s.\n", str_error(rc));
+			break;
+		}
+		
+		printf("Got buffer: %p, size: %zu, max size: %zu\n", event, 
+		    actual_size, size);
+		
+		print_key(event, size, report);
+		
+		async_usleep(10000);
+	}
 	
 	return 0;
Index: uspace/drv/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/usbhid/generic/hiddev.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/drv/usbhid/generic/hiddev.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -62,8 +62,13 @@
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
 
-static int usb_generic_hid_get_event(ddf_fun_t *fun, int32_t *buffer, 
+static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
     size_t size, size_t *act_size, unsigned int flags);
 
 static int usb_generic_hid_client_connected(ddf_fun_t *fun);
+
+static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun);
+
+static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
+    size_t size, size_t *actual_size);
 
 /*----------------------------------------------------------------------------*/
@@ -71,5 +76,7 @@
 static usbhid_iface_t usb_generic_iface = {
 	.get_event = usb_generic_hid_get_event,
-	.get_event_length = usb_generic_hid_get_event_length
+	.get_event_length = usb_generic_hid_get_event_length,
+	.get_report_descriptor_length = usb_generic_get_report_descriptor_length,
+	.get_report_descriptor = usb_generic_get_report_descriptor
 };
 
@@ -83,5 +90,8 @@
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
 {
-	if (fun == NULL || fun->driver_data) {
+	usb_log_debug("Generic HID: Get event length (fun: %p, "
+	    "fun->driver_data: %p.\n", fun, fun->driver_data);
+	
+	if (fun == NULL || fun->driver_data == NULL) {
 		return 0;
 	}
@@ -89,13 +99,19 @@
 	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
 	
-	return hid_dev->input_report_size;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_generic_hid_get_event(ddf_fun_t *fun, int32_t *buffer, 
+	usb_log_debug("hid_dev: %p, Max input report size (%d).\n",
+	    hid_dev, hid_dev->max_input_report_size);
+	
+	return hid_dev->max_input_report_size;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
     size_t size, size_t *act_size, unsigned int flags)
 {
-	if (fun == NULL || fun->driver_data) {
+	usb_log_debug("Generic HID: Get event.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		usb_log_debug("No function");
 		return EINVAL;
 	}
@@ -104,4 +120,6 @@
 	
 	if (hid_dev->input_report_size > size) {
+		usb_log_debug("input_report_size > size (%zu, %zu)\n", 
+		    hid_dev->input_report_size, size);
 		return EINVAL;	// TODO: other error code
 	}
@@ -109,4 +127,6 @@
 	/*! @todo This should probably be atomic. */
 	if (usb_hid_report_ready()) {
+		usb_log_debug("Report ready, size: %zu\n", 
+		    hid_dev->input_report_size);
 		memcpy(buffer, hid_dev->input_report, 
 		    hid_dev->input_report_size);
@@ -120,4 +140,47 @@
 	// note that we already received this report
 //	report_received = true;
+	usb_log_debug("OK\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
+{
+	usb_log_debug("Generic HID: Get report descriptor length.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		usb_log_debug("No function");
+		return EINVAL;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	printf("hid_dev->report_desc_size = %zu\n", hid_dev->report_desc_size);
+	
+	return hid_dev->report_desc_size;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
+    size_t size, size_t *actual_size)
+{
+	usb_log_debug("Generic HID: Get report descriptor.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		usb_log_debug("No function");
+		return EINVAL;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	if (hid_dev->report_desc_size > size) {
+		return EINVAL;	// TODO: other error code
+	}
+	
+	memcpy(desc, hid_dev->report_desc, hid_dev->report_desc_size);
+	*actual_size = hid_dev->report_desc_size;
 	
 	return EOK;
@@ -128,4 +191,5 @@
 static int usb_generic_hid_client_connected(ddf_fun_t *fun)
 {
+	usb_log_debug("Generic HID: Client connected.\n");
 	usb_hid_report_received();
 	return EOK;
@@ -145,4 +209,7 @@
 		return ENOMEM;
 	}
+	
+	fun->ops = &usb_generic_hid_ops;
+	fun->driver_data = hid_dev;
 
 	int rc = ddf_fun_bind(fun);
@@ -154,6 +221,5 @@
 	}
 	
-	fun->ops = &usb_generic_hid_ops;
-	fun->driver_data = hid_dev;
+	usb_log_debug("HID function created. Handle: %d\n", fun->handle);
 	
 	return EOK;
Index: uspace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/drv/usbhid/kbd/kbddev.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -798,4 +798,7 @@
 	}
 	
+	usb_log_debug("%s function created. Handle: %d\n", HID_KBD_FUN_NAME,
+	    fun->handle);
+	
 	usb_log_debug("Adding DDF function to class %s...\n", 
 	    HID_KBD_CLASS_NAME);
Index: uspace/drv/usbhid/multimedia/keymap.c
===================================================================
--- uspace/drv/usbhid/multimedia/keymap.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/drv/usbhid/multimedia/keymap.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -48,11 +48,4 @@
  */
 static int usb_hid_keymap_consumer[0x29c] = {
-	[0xf] = KC_F1, /* Just for testing purposes */
-	[0x5] = KC_F2, /* 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 */
@@ -63,685 +56,14 @@
 	[0xe9] = KC_F5,   /* Volume Increment */
 	[0xea] = KC_F4,   /* Volume Decrement */
-	[0x183] = 0,      /* AL Consumer Control Configuration */
+	[0x183] = KC_F1,      /* AL Consumer Control Configuration */
 	[0x18a] = 0,      /* AL Email Reader */
 	[0x192] = 0,      /* AL Calculator */
 	[0x221] = 0,      /* AC Search */
-	[0x223] = 0,      /* AC Home */
+	[0x223] = KC_F6,      /* AC Home */
 	[0x224] = 0,      /* AC Back */
 	[0x225] = 0,      /* AC Forward */
 	[0x226] = 0,      /* AC Stop */
-	[0x227] = KC_F1,  /* AC Refresh */
-	[0x22a] = KC_F6   /* AC Bookmarks */
-};
-
-static const char *usb_hid_consumer_usage_str[0x29d] = {
-	[0x01] = "Consumer Control",
-	[0x02] = "Numeric Key Pad",
-	[0x03] = "Programmable Buttons",
-	[0x04] = "Microphone",
-	[0x05] = "Headphone",
-	[0x06] = "Graphic Equalizer",
-	[0x07] = "Reserved",
-	[0x08] = "Reserved",
-	[0x09] = "Reserved",
-	[0x0a] = "Reserved",
-	[0x0b] = "Reserved",
-	[0x0c] = "Reserved",
-	[0x0d] = "Reserved",
-	[0x0e] = "Reserved",
-	[0x0f] = "Reserved",
-	[0x10] = "Reserved",
-	[0x11] = "Reserved",
-	[0x12] = "Reserved",
-	[0x13] = "Reserved",
-	[0x14] = "Reserved",
-	[0x15] = "Reserved",
-	[0x16] = "Reserved",
-	[0x17] = "Reserved",
-	[0x18] = "Reserved",
-	[0x19] = "Reserved",
-	[0x1a] = "Reserved",
-	[0x1b] = "Reserved",
-	[0x1c] = "Reserved",
-	[0x1d] = "Reserved",
-	[0x1e] = "Reserved",
-	[0x1f] = "Reserved",
-	[0x20] = "+10",
-	[0x21] = "+100",
-	[0x22] = "AM/PM",
-	[0x23] = "Reserved",
-	[0x24] = "Reserved",
-	[0x25] = "Reserved",
-	[0x26] = "Reserved",
-	[0x27] = "Reserved",
-	[0x28] = "Reserved",
-	[0x29] = "Reserved",
-	[0x2a] = "Reserved",
-	[0x2b] = "Reserved",
-	[0x2c] = "Reserved",
-	[0x2d] = "Reserved",
-	[0x2e] = "Reserved",
-	[0x2f] = "Reserved",
-	[0x30] = "Reserved",
-	[0x31] = "Reserved",
-	[0x32] = "Reserved",
-	[0x33] = "Reserved",
-	[0x34] = "Reserved",
-	[0x35] = "Reserved",
-	[0x36] = "Reserved",
-	[0x37] = "Reserved",
-	[0x38] = "Reserved",
-	[0x39] = "Reserved",
-	[0x3a] = "Reserved",
-	[0x3b] = "Reserved",
-	[0x3c] = "Reserved",
-	[0x3d] = "Reserved",
-	[0x3e] = "Reserved",
-	[0x3f] = "Reserved",
-	[0x40] = "Menu",
-	[0x41] = "Menu Pick",
-	[0x42] = "Menu Up",
-	[0x43] = "Menu Down",
-	[0x44] = "Menu Left",
-	[0x45] = "Menu Right",
-	[0x46] = "Menu Escape",
-	[0x47] = "Menu Value Increase",
-	[0x48] = "Menu Value Decrease",
-	[0x49] = "Reserved",
-	[0x4a] = "Reserved",
-	[0x4b] = "Reserved",
-	[0x4c] = "Reserved",
-	[0x4d] = "Reserved",
-	[0x4e] = "Reserved",
-	[0x4f] = "Reserved",
-	[0x50] = "Reserved",
-	[0x51] = "Reserved",
-	[0x52] = "Reserved",
-	[0x53] = "Reserved",
-	[0x54] = "Reserved",
-	[0x55] = "Reserved",
-	[0x56] = "Reserved",
-	[0x57] = "Reserved",
-	[0x58] = "Reserved",
-	[0x59] = "Reserved",
-	[0x5a] = "Reserved",
-	[0x5b] = "Reserved",
-	[0x5c] = "Reserved",
-	[0x5d] = "Reserved",
-	[0x5e] = "Reserved",
-	[0x5f] = "Reserved",
-	[0x60] = "Data On Screen",
-	[0x61] = "Closed Caption",
-	[0x62] = "Closed Caption Select",
-	[0x63] = "VCR/TV",
-	[0x64] = "Broadcast Mode",
-	[0x65] = "Snapshot",
-	[0x66] = "Still",
-	[0x67] = "Reserved",
-	[0x68] = "Reserved",
-	[0x69] = "Reserved",
-	[0x6a] = "Reserved",
-	[0x6b] = "Reserved",
-	[0x6c] = "Reserved",
-	[0x6d] = "Reserved",
-	[0x6e] = "Reserved",
-	[0x6f] = "Reserved",
-	[0x70] = "Reserved",
-	[0x71] = "Reserved",
-	[0x72] = "Reserved",
-	[0x73] = "Reserved",
-	[0x74] = "Reserved",
-	[0x75] = "Reserved",
-	[0x76] = "Reserved",
-	[0x77] = "Reserved",
-	[0x78] = "Reserved",
-	[0x79] = "Reserved",
-	[0x7a] = "Reserved",
-	[0x7b] = "Reserved",
-	[0x7c] = "Reserved",
-	[0x7d] = "Reserved",
-	[0x7e] = "Reserved",
-	[0x7f] = "Reserved",
-	[0x80] = "Selection",
-	[0x81] = "Assign Selection",
-	[0x82] = "Mode Step",
-	[0x83] = "Recall Last",
-	[0x84] = "Enter Channel",
-	[0x85] = "Order Movie",
-	[0x86] = "Channel",
-	[0x87] = "Media Selection",
-	[0x88] = "Media Select Computer",
-	[0x89] = "Media Select TV",
-	[0x8a] = "Media Select WWW",
-	[0x8b] = "Media Select DVD",
-	[0x8c] = "Media Select Telephone",
-	[0x8d] = "Media Select Program Guide",
-	[0x8e] = "Media Select Video Phone",
-	[0x8f] = "Media Select Games",
-	[0x90] = "Media Select Messages",
-	[0x91] = "Media Select CD",
-	[0x92] = "Media Select VCR",
-	[0x93] = "Media Select Tuner",
-	[0x94] = "Quit",
-	[0x95] = "Help",
-	[0x96] = "Media Select Tape",
-	[0x97] = "Media Select Cable",
-	[0x98] = "Media Select Satellite",
-	[0x99] = "Media Select Security",
-	[0x9a] = "Media Select Home",
-	[0x9b] = "Media Select Call",
-	[0x9c] = "Channel Increment",
-	[0x9d] = "Channel Decrement",
-	[0x9e] = "Media Select SAP",
-	[0x9f] = "Reserved",
-	[0xa0] = "VCR Plus",
-	[0xa1] = "Once",
-	[0xa2] = "Daily",
-	[0xa3] = "Weekly",
-	[0xa4] = "Monthly",
-	[0xa5] = "Reserved",
-	[0xa6] = "Reserved",
-	[0xa7] = "Reserved",
-	[0xa8] = "Reserved",
-	[0xa9] = "Reserved",
-	[0xaa] = "Reserved",
-	[0xab] = "Reserved",
-	[0xac] = "Reserved",
-	[0xad] = "Reserved",
-	[0xae] = "Reserved",
-	[0xaf] = "Reserved",
-	[0xb0] = "Play",
-	[0xb1] = "Pause",
-	[0xb2] = "Record",
-	[0xb3] = "Fast Forward",
-	[0xb4] = "Rewind",
-	[0xb5] = "Scan Next Track",
-	[0xb6] = "Scan Previous Trac",
-	[0xb7] = "Stop",
-	[0xb8] = "Eject",
-	[0xb9] = "Random Play",
-	[0xba] = "Select Disc",
-	[0xbb] = "Enter Disc",
-	[0xbc] = "Repeat",
-	[0xbd] = "Tracking",
-	[0xbe] = "Track Normal",
-	[0xbf] = "Slow Tracking",
-	[0xc0] = "Frame Forward",
-	[0xc1] = "Frame Back",
-	[0xc2] = "Mark",
-	[0xc3] = "Clear Mark",
-	[0xc4] = "Repeat From Mark",
-	[0xc5] = "Return to Mark",
-	[0xc6] = "Search Mark Forward",
-	[0xc7] = "Search Mark Backwards",
-	[0xc8] = "Counter Reset",
-	[0xc9] = "Show Counter",
-	[0xca] = "Tracking Increment",
-	[0xcb] = "Tracking Decrement",
-	[0xcc] = "Stop/Eject",
-	[0xcd] = "Play/Pause",
-	[0xce] = "Play/Skip",
-	[0xcf] = "Reserved",
-	[0xd0] = "Reserved",
-	[0xd1] = "Reserved",
-	[0xd2] = "Reserved",
-	[0xd3] = "Reserved",
-	[0xd4] = "Reserved",
-	[0xd5] = "Reserved",
-	[0xd6] = "Reserved",
-	[0xd7] = "Reserved",
-	[0xd8] = "Reserved",
-	[0xd9] = "Reserved",
-	[0xda] = "Reserved",
-	[0xdb] = "Reserved",
-	[0xdc] = "Reserved",
-	[0xdd] = "Reserved",
-	[0xde] = "Reserved",
-	[0xdf] = "Reserved",
-	[0xe0] = "Volume",
-	[0xe1] = "Balance",
-	[0xe2] = "Mute",
-	[0xe3] = "Bass",
-	[0xe4] = "Treble",
-	[0xe5] = "Bass Boost",
-	[0xe6] = "Surround Mode",
-	[0xe7] = "Loudness",
-	[0xe8] = "MPX",
-	[0xe9] = "Volume Increment",
-	[0xea] = "Volume Decrement",
-	[0xeb] = "Reserved",
-	[0xec] = "Reserved",
-	[0xed] = "Reserved",
-	[0xee] = "Reserved",
-	[0xef] = "Reserved",
-	[0xf0] = "Speed Select",
-	[0xf1] = "Playback Speed",
-	[0xf2] = "Standard Play",
-	[0xf3] = "Long Play",
-	[0xf4] = "Extended Play",
-	[0xf5] = "Slow",
-	[0xf6] = "Reserved",
-	[0xf7] = "Reserved",
-	[0xf8] = "Reserved",
-	[0xf9] = "Reserved",
-	[0xfa] = "Reserved",
-	[0xfb] = "Reserved",
-	[0xfc] = "Reserved",
-	[0xfd] = "Reserved",
-	[0xfe] = "Reserved",
-	[0xff] = "Reserved",
-	[0x100] = "Fan Enable",
-	[0x101] = "Fan Speed",
-	[0x102] = "Light Enable",
-	[0x103] = "Light Illumination Level",
-	[0x104] = "Climate Control Enable",
-	[0x105] = "Room Temperature",
-	[0x106] = "Security Enable",
-	[0x107] = "Fire Alarm",
-	[0x108] = "Police Alarm",
-	[0x109] = "Proximity",
-	[0x10a] = "Motion",
-	[0x10b] = "Duress Alarm",
-	[0x10c] = "Holdup Alarm",
-	[0x10d] = "Medical Alarm",
-	[0x10e] = "Reserved",
-	[0x10f] = "Reserved",
-	[0x110] = "Reserved",
-	[0x111] = "Reserved",
-	[0x112] = "Reserved",
-	[0x113] = "Reserved",
-	[0x114] = "Reserved",
-	[0x115] = "Reserved",
-	[0x116] = "Reserved",
-	[0x117] = "Reserved",
-	[0x118] = "Reserved",
-	[0x119] = "Reserved",
-	[0x11a] = "Reserved",
-	[0x11b] = "Reserved",
-	[0x11c] = "Reserved",
-	[0x11d] = "Reserved",
-	[0x11e] = "Reserved",
-	[0x11f] = "Reserved",
-	[0x120] = "Reserved", 
-	[0x121] = "Reserved",
-	[0x122] = "Reserved",
-	[0x123] = "Reserved",
-	[0x124] = "Reserved",
-	[0x125] = "Reserved",
-	[0x126] = "Reserved",
-	[0x127] = "Reserved",
-	[0x128] = "Reserved",
-	[0x129] = "Reserved",
-	[0x12a] = "Reserved",
-	[0x12b] = "Reserved",
-	[0x12c] = "Reserved",
-	[0x12d] = "Reserved",
-	[0x12e] = "Reserved",
-	[0x12f] = "Reserved",
-	[0x130] = "Reserved", 
-	[0x131] = "Reserved",
-	[0x132] = "Reserved",
-	[0x133] = "Reserved",
-	[0x134] = "Reserved",
-	[0x135] = "Reserved",
-	[0x136] = "Reserved",
-	[0x137] = "Reserved",
-	[0x138] = "Reserved",
-	[0x139] = "Reserved",
-	[0x13a] = "Reserved",
-	[0x13b] = "Reserved",
-	[0x13c] = "Reserved",
-	[0x13d] = "Reserved",
-	[0x13e] = "Reserved",
-	[0x13f] = "Reserved",
-	[0x140] = "Reserved", 
-	[0x141] = "Reserved",
-	[0x142] = "Reserved",
-	[0x143] = "Reserved",
-	[0x144] = "Reserved",
-	[0x145] = "Reserved",
-	[0x146] = "Reserved",
-	[0x147] = "Reserved",
-	[0x148] = "Reserved",
-	[0x149] = "Reserved",
-	[0x14a] = "Reserved",
-	[0x14b] = "Reserved",
-	[0x14c] = "Reserved",
-	[0x14d] = "Reserved",
-	[0x14e] = "Reserved",
-	[0x14f] = "Reserved",
-	[0x150] = "Balance Right",
-	[0x151] = "Balance Left",
-	[0x152] = "Bass Increment",
-	[0x153] = "Bass Decrement",
-	[0x154] = "Treble Increment",
-	[0x155] = "Treble Decrement",
-	[0x156] = "Reserved",
-	[0x157] = "Reserved",
-	[0x158] = "Reserved",
-	[0x159] = "Reserved",
-	[0x15a] = "Reserved",
-	[0x15b] = "Reserved",
-	[0x15c] = "Reserved",
-	[0x15d] = "Reserved",
-	[0x15e] = "Reserved",
-	[0x15f] = "Reserved",
-	[0x160] = "Speaker System",
-	[0x161] = "Channel Left",
-	[0x162] = "Channel Right",
-	[0x163] = "Channel Center",
-	[0x164] = "Channel Front",
-	[0x165] = "Channel Center Front",
-	[0x166] = "Channel Side",
-	[0x167] = "Channel Surround",
-	[0x168] = "Channel Low Frequency Enhancement",
-	[0x169] = "Channel Top",
-	[0x16a] = "Channel Unknown",
-	[0x16b] = "Reserved",
-	[0x16c] = "Reserved",
-	[0x16d] = "Reserved",
-	[0x16e] = "Reserved",
-	[0x16f] = "Reserved",
-	[0x170] = "Sub-channel",
-	[0x171] = "Sub-channel Increment",
-	[0x172] = "Sub-channel Decrement",
-	[0x173] = "Alternate Audio Increment",
-	[0x174] = "Alternate Audio Decrement",
-	[0x175] = "Reserved",
-	[0x176] = "Reserved",
-	[0x177] = "Reserved",
-	[0x178] = "Reserved",
-	[0x179] = "Reserved",
-	[0x17a] = "Reserved",
-	[0x17b] = "Reserved",
-	[0x17c] = "Reserved",
-	[0x17d] = "Reserved",
-	[0x17e] = "Reserved",
-	[0x17f] = "Reserved",
-	[0x180] = "Application Launch Buttons",
-	[0x181] = "AL Launch Buttion Configuration Tool",
-	[0x182] = "AL Programmable Button Configuration",
-	[0x183] = "AL Consumer Control Configuration",
-	[0x184] = "AL Word Processor",
-	[0x185] = "AL Text Editor",
-	[0x186] = "AL Spreadsheet",
-	[0x187] = "AL Graphics Editor",
-	[0x188] = "AL Presentation App",
-	[0x189] = "AL Database App",
-	[0x18a] = "AL Email Reader",
-	[0x18b] = "AL Newsreader",
-	[0x18c] = "AL Voicemail",
-	[0x18d] = "AL Contacts/Address Book",
-	[0x18e] = "AL Calendar/Schedule",
-	[0x18f] = "AL Task/Project Manager",
-	[0x190] = "AL Log/Journal/Timecard",
-	[0x191] = "AL Checkbook/Finance",
-	[0x192] = "AL Calculator",
-	[0x193] = "AL A/V Capture/Playback",
-	[0x194] = "AL Local Machine Browser",
-	[0x195] = "AL LAN/WAN Browser",
-	[0x196] = "AL Internet Browser",
-	[0x197] = "AL Remote Networking/ISP Connect",
-	[0x198] = "AL Network Conference",
-	[0x199] = "AL Network Chat",
-	[0x19a] = "AL Telephony/Dialer",
-	[0x19b] = "AL Logon",
-	[0x19c] = "AL Logoff",
-	[0x19d] = "AL Logon/Logoff",
-	[0x19e] = "AL Terminal Lock/Screensaver",
-	[0x19f] = "AL Control Panel",
-	[0x1a0] = "AL Command Line Processor/Run",
-	[0x1a1] = "AL Process/Task Manager",
-	[0x1a2] = "AL Select Task/Application",
-	[0x1a3] = "AL Next Task/Application",
-	[0x1a4] = "AL Previous Task/Application",
-	[0x1a5] = "AL Preemptive Halt Task/Application",
-	[0x1a6] = "AL Integrated Help Center",
-	[0x1a7] = "AL Documents",
-	[0x1a8] = "AL Thesaurus",
-	[0x1a9] = "AL Dictionary",
-	[0x1aa] = "AL Desktop",
-	[0x1ab] = "AL Spell Check",
-	[0x1ac] = "AL Grammar Check",
-	[0x1ad] = "AL Wireless Status",
-	[0x1ae] = "AL Keyboard Layout",
-	[0x1af] = "AL Virus Protection",
-	[0x1b0] = "AL Encryption",
-	[0x1b1] = "AL Screen Saver",
-	[0x1b2] = "AL Alarms",
-	[0x1b3] = "AL Clock",
-	[0x1b4] = "AL File Browser",
-	[0x1b5] = "AL Power Status",
-	[0x1b6] = "AL Image Browser",
-	[0x1b7] = "AL Audio Browser",
-	[0x1b8] = "AL Movie Browser",
-	[0x1b9] = "AL Digital Rights Manager",
-	[0x1ba] = "AL Digital Wallet",
-	[0x1bb] = "Reserved",
-	[0x1bc] = "AL Instant Messaging",
-	[0x1bd] = "AL OEM Features Tips/Tutorial Browser",
-	[0x1be] = "AL OEM Help",
-	[0x1bf] = "AL Online Community",
-	[0x1c0] = "AL Entertainment Content Browser",
-	[0x1c1] = "AL Online Shopping Browser",
-	[0x1c2] = "AL SmartCard Information/Help",
-	[0x1c3] = "AL Market Monitor/Finance Browser",
-	[0x1c4] = "AL Customized Corporate News Browser",
-	[0x1c5] = "AL Online Activity Browser",
-	[0x1c6] = "AL Research/Search Browser",
-	[0x1c7] = "AL Audio Player",
-	[0x1c8] = "Reserved",
-	[0x1c9] = "Reserved",
-	[0x1ca] = "Reserved",
-	[0x1cb] = "Reserved",
-	[0x1cc] = "Reserved",
-	[0x1cd] = "Reserved",
-	[0x1ce] = "Reserved",
-	[0x1cf] = "Reserved",
-	[0x1d0] = "Reserved",
-	[0x1d1] = "Reserved",
-	[0x1d2] = "Reserved",
-	[0x1d3] = "Reserved",
-	[0x1d4] = "Reserved",
-	[0x1d5] = "Reserved",
-	[0x1d6] = "Reserved",
-	[0x1d7] = "Reserved",
-	[0x1d8] = "Reserved",
-	[0x1d9] = "Reserved",
-	[0x1da] = "Reserved",
-	[0x1db] = "Reserved",
-	[0x1dc] = "Reserved",
-	[0x1dd] = "Reserved",
-	[0x1de] = "Reserved",
-	[0x1df] = "Reserved",
-	[0x1e0] = "Reserved",
-	[0x1e1] = "Reserved",
-	[0x1e2] = "Reserved",
-	[0x1e3] = "Reserved",
-	[0x1e4] = "Reserved",
-	[0x1e5] = "Reserved",
-	[0x1e6] = "Reserved",
-	[0x1e7] = "Reserved",
-	[0x1e8] = "Reserved",
-	[0x1e9] = "Reserved",
-	[0x1ea] = "Reserved",
-	[0x1eb] = "Reserved",
-	[0x1ec] = "Reserved",
-	[0x1ed] = "Reserved",
-	[0x1ee] = "Reserved",
-	[0x1ef] = "Reserved",
-	[0x1f0] = "Reserved",
-	[0x1f1] = "Reserved",
-	[0x1f2] = "Reserved",
-	[0x1f3] = "Reserved",
-	[0x1f4] = "Reserved",
-	[0x1f5] = "Reserved",
-	[0x1f6] = "Reserved",
-	[0x1f7] = "Reserved",
-	[0x1f8] = "Reserved",
-	[0x1f9] = "Reserved",
-	[0x1fa] = "Reserved",
-	[0x1fb] = "Reserved",
-	[0x1fc] = "Reserved",
-	[0x1fd] = "Reserved",
-	[0x1fe] = "Reserved",
-	[0x1ff] = "Reserved",
-	[0x200] = "Generic GUI Application Controls",
-	[0x201] = "AC New",
-	[0x202] = "AC Open",
-	[0x203] = "AC Close",
-	[0x204] = "AC Exit",
-	[0x205] = "AC Maximize",
-	[0x206] = "AC Minimize",
-	[0x207] = "AC Save",
-	[0x208] = "AC Print",
-	[0x209] = "AC Properties",
-	[0x20a] = "",
-	[0x20b] = "",
-	[0x20c] = "",
-	[0x20d] = "",
-	[0x20e] = "",
-	[0x20f] = "",
-	[0x210] = "",
-	[0x211] = "",
-	[0x212] = "",
-	[0x213] = "",
-	[0x214] = "",
-	[0x215] = "",
-	[0x216] = "",
-	[0x217] = "",
-	[0x218] = "",
-	[0x219] = "",
-	[0x21a] = "AC Undo",
-	[0x21b] = "AC Copy",
-	[0x21c] = "AC Cut",
-	[0x21d] = "AC Paste",
-	[0x21e] = "AC Select All",
-	[0x21f] = "AC Find",
-	[0x220] = "AC Find and Replace",
-	[0x221] = "AC Search",
-	[0x222] = "AC Go To",
-	[0x223] = "AC Home",
-	[0x224] = "AC Back",
-	[0x225] = "AC Forward",
-	[0x226] = "AC Stop",
-	[0x227] = "AC Refresh",
-	[0x228] = "AC Previous Link",
-	[0x229] = "AC Next Link",
-	[0x22a] = "AC Bookmarks",
-	[0x22b] = "AC History",
-	[0x22c] = "AC Subscriptions",
-	[0x22d] = "AC Zoom In",
-	[0x22e] = "AC Zoom Out",
-	[0x22f] = "AC Zoom",
-	[0x230] = "AC Full Screen View",
-	[0x231] = "AC Normal View",
-	[0x232] = "AC View Toggle",
-	[0x233] = "AC Scroll Up",
-	[0x234] = "AC Scroll Down",
-	[0x235] = "AC Scroll",
-	[0x236] = "AC Pan Left",
-	[0x237] = "AC Pan Right",
-	[0x238] = "AC Pan",
-	[0x239] = "AC New Window",
-	[0x23a] = "AC Tile Horizontally",
-	[0x23b] = "AC Tile Vertically",
-	[0x23c] = "AC Format",
-	[0x23d] = "AC Edit",
-	[0x23e] = "AC Bold",
-	[0x23f] = "AC Italics",
-	[0x240] = "AC Undeline",
-	[0x241] = "AC Strikethrough",
-	[0x242] = "AC Subscript",
-	[0x243] = "AC Superscript",
-	[0x244] = "AC All Caps",
-	[0x245] = "AC Rotate",
-	[0x246] = "AC Resize",
-	[0x247] = "AC Flip Horizontal",
-	[0x248] = "AC Flip Vertical",
-	[0x249] = "AC Mirror Horizontal",
-	[0x24a] = "AC Mirror Vertical",
-	[0x24b] = "AC Font Select",
-	[0x24c] = "AC Font Color",
-	[0x24d] = "AC Font Size",
-	[0x24e] = "AC Justify Left",
-	[0x24f] = "AC Justify Center H",
-	[0x250] = "AC Justify Right",
-	[0x251] = "AC Justify Block H",
-	[0x252] = "AC Justify Top",
-	[0x253] = "AC Justify Center V",
-	[0x254] = "AC Justify Bottom",
-	[0x255] = "AC Justify Block V",
-	[0x256] = "AC Indent Decrease",
-	[0x257] = "AC Indent Increase",
-	[0x258] = "AC Numbered List",
-	[0x259] = "AC Restart Numbering",
-	[0x25a] = "AC Bulleted List",
-	[0x25b] = "AC Promote",
-	[0x25c] = "AC Demote",
-	[0x25d] = "AC Yes",
-	[0x25e] = "AC No",
-	[0x25f] = "AC Cancel",
-	[0x260] = "AC Catalog",
-	[0x261] = "AC Buy/Checkout",
-	[0x262] = "AC Add to Cart",
-	[0x263] = "AC Expand",
-	[0x264] = "AC Expand All",
-	[0x265] = "AC Collapse",
-	[0x266] = "AC Collapse All",
-	[0x267] = "AC Print Preview",
-	[0x268] = "AC Paste Special",
-	[0x269] = "AC Insert Mode",
-	[0x26a] = "AC Delete",
-	[0x26b] = "AC Lock",
-	[0x26c] = "AC Unlock",
-	[0x26d] = "AC Protect",
-	[0x26e] = "AC Unprotect",
-	[0x26f] = "AC Attach Comment",
-	[0x270] = "AC Delete Comment",
-	[0x271] = "AC View Comment",
-	[0x272] = "AC Select Word",
-	[0x273] = "AC Select Sentence",
-	[0x274] = "AC Select Paragraph",
-	[0x275] = "AC Select Column",
-	[0x276] = "AC Select Row",
-	[0x277] = "AC Select Table",
-	[0x278] = "AC Select Object",
-	[0x279] = "AC Redo/Repeat",
-	[0x27a] = "AC Sort",
-	[0x27b] = "AC Sort Ascending",
-	[0x27c] = "AC Sort Descending",
-	[0x27d] = "AC Filter",
-	[0x27e] = "AC Set Clock",
-	[0x27f] = "AC View Clock",
-	[0x280] = "AC Select Time Zone",
-	[0x281] = "AC Edit Time Zones",
-	[0x282] = "AC Set Alarm",
-	[0x283] = "AC Clear Alarm",
-	[0x284] = "AC Snooze Alarm",
-	[0x285] = "AC Reset Alarm",
-	[0x286] = "AC Synchronize",
-	[0x287] = "AC Send/Receive",
-	[0x288] = "AC Send To",
-	[0x289] = "AC Reply",
-	[0x28a] = "AC Reply All",
-	[0x28b] = "AC Forward Msg",
-	[0x28c] = "AC Send",
-	[0x28d] = "AC Attach File",
-	[0x28e] = "AC Upload",
-	[0x28f] = "AC Download (Save Target As)",
-	[0x290] = "AC Set Borders",
-	[0x291] = "AC Insert Row",
-	[0x292] = "AC Insert Column",
-	[0x293] = "AC Insert File",
-	[0x294] = "AC Insert Picture",
-	[0x295] = "AC Insert Object",
-	[0x296] = "AC Insert Symbol",
-	[0x297] = "AC Save and Close",
-	[0x298] = "AC Rename",
-	[0x299] = "AC Merge",
-	[0x29a] = "AC Split",
-	[0x29b] = "AC Distrubute Horizontally",
-	[0x29c] = "AC Distrubute Vertically"
+	[0x227] = 0,  /* AC Refresh */
+	[0x22a] = 0   /* AC Bookmarks */
 };
 
@@ -769,23 +91,4 @@
 
 /**
- * Translates USB HID Usages from the Consumer Page into their string 
- * representation.
- *
- * @param usage USB HID Consumer Page Usage number.
- * 
- * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
- */
-const char *usb_multimedia_usage_to_str(int usage)
-{
-	size_t map_length = sizeof(usb_hid_consumer_usage_str) / sizeof(char *);
-
-	if ((usage < 0) || ((size_t)usage >= map_length))
-		return "Unknown usage";
-
-	/*! @todo What if the usage is not in the table? */
-	return usb_hid_consumer_usage_str[usage];
-}
-
-/**
  * @}
  */
Index: uspace/drv/usbhid/multimedia/keymap.h
===================================================================
--- uspace/drv/usbhid/multimedia/keymap.h	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/drv/usbhid/multimedia/keymap.h	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -39,6 +39,4 @@
 unsigned int usb_multimedia_map_usage(int usage);
 
-const char *usb_multimedia_usage_to_str(int usage);
-
 #endif /* USB_HID_MULTIMEDIA_KEYMAP_H_ */
 
Index: uspace/drv/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/usbhid/multimedia/multimedia.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/drv/usbhid/multimedia/multimedia.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -43,4 +43,5 @@
 #include <usb/debug.h>
 #include <usb/hid/usages/core.h>
+#include <usb/hid/usages/consumer.h>
 
 #include <errno.h>
@@ -210,4 +211,6 @@
 	}
 	
+	usb_log_debug("%s function created. Handle: %d\n", NAME, fun->handle);
+	
 	rc = ddf_fun_add_to_class(fun, "keyboard");
 	if (rc != EOK) {
@@ -247,5 +250,5 @@
 	
 	multim_dev->key_count = usb_hid_report_size(
-	    hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
+	    hid_dev->report, 1, USB_HID_REPORT_TYPE_INPUT);
 
 	usb_hid_report_path_free(path);
@@ -357,5 +360,5 @@
 			    usb_multimedia_map_usage(field->usage);
 			const char *key_str = 
-			    usb_multimedia_usage_to_str(field->usage);
+			    usbhid_multimedia_usage_to_str(field->usage);
 			usb_log_info("Pressed key: %s\n", key_str);
 			usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS, 
Index: uspace/drv/usbhid/subdrivers.c
===================================================================
--- uspace/drv/usbhid/subdrivers.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/drv/usbhid/subdrivers.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -38,7 +38,7 @@
 #include <usb/hid/hidpath.h>
 
-//#include "lgtch-ultrax/lgtch-ultrax.h"
 #include "multimedia/multimedia.h"
 #include "mouse/mousedev.h"
+#include "generic/hiddev.h"
 
 static usb_hid_subdriver_usage_t path_kbd[] = {
@@ -58,8 +58,12 @@
 };
 
+//static usb_hid_subdriver_usage_t generic_hid_key_path[] = {
+//	{0, 0}
+//};
+
 const usb_hid_subdriver_mapping_t usb_hid_subdrivers[] = {
 	{
 		path_kbd,
-		-1,
+		0,
 		USB_HID_PATH_COMPARE_BEGIN,
 		-1,
@@ -88,5 +92,5 @@
 	{
 		path_mouse,
-		-1,
+		0,
 		USB_HID_PATH_COMPARE_BEGIN,
 		-1,
@@ -99,4 +103,17 @@
 		}
 	},
+//	{
+//		generic_hid_key_path,
+//		0,
+//		USB_HID_PATH_COMPARE_ANYWHERE,
+//		-1,
+//		-1,
+//		{
+//			.init = usb_generic_hid_init,
+//			.deinit = NULL,
+//			.poll = usb_generic_hid_polling_callback,
+//			.poll_end = NULL
+//		}
+//	},
 	{NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL, NULL}}
 };
Index: uspace/drv/usbhid/usbhid.c
===================================================================
--- uspace/drv/usbhid/usbhid.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/drv/usbhid/usbhid.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -234,5 +234,7 @@
 	}
 	
-	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(count * 
+	// add one generic HID subdriver per device
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) * 
 	    sizeof(usb_hid_subdriver_t));
 	if (hid_dev->subdrivers == NULL) {
@@ -247,5 +249,10 @@
 	}
 	
-	hid_dev->subdriver_count = count;
+	hid_dev->subdrivers[count].init = usb_generic_hid_init;
+	hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback;
+	hid_dev->subdrivers[count].deinit = NULL;
+	hid_dev->subdrivers[count].poll_end = NULL;
+	
+	hid_dev->subdriver_count = count + 1;
 	
 	return EOK;
@@ -307,4 +314,5 @@
 		
 		if (matched) {
+			usb_log_debug("Subdriver matched.\n");
 			subdrivers[count++] = &mapping->subdriver;
 		}
@@ -348,4 +356,38 @@
 /*----------------------------------------------------------------------------*/
 
+static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->report != NULL);
+	
+	uint8_t report_id = 0;
+	size_t size = usb_hid_report_byte_size(hid_dev->report, report_id, 
+	    USB_HID_REPORT_TYPE_INPUT);
+	
+	size_t max_size = 0;
+	
+	do {
+		max_size = (size > max_size) ? size : max_size;
+		size = usb_hid_report_byte_size(hid_dev->report, report_id, 
+		    USB_HID_REPORT_TYPE_INPUT);
+		report_id = usb_hid_get_next_report_id(hid_dev->report, 
+		    report_id, USB_HID_REPORT_TYPE_INPUT);
+	} while (report_id != 0);
+	
+	usb_log_debug("Max size of input report: %zu\n", max_size);
+	
+	hid_dev->max_input_report_size = max_size;
+	assert(hid_dev->input_report == NULL);
+	
+	hid_dev->input_report = malloc(max_size);
+	if (hid_dev->input_report == NULL) {
+		return ENOMEM;
+	}
+	memset(hid_dev->input_report, 0, max_size);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
 usb_hid_dev_t *usb_hid_new(void)
 {
@@ -402,5 +444,5 @@
 	/* Get the report descriptor and parse it. */
 	rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 
-	    hid_dev->report);
+	    hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
 	
 	bool fallback = false;
@@ -483,4 +525,10 @@
 	}
 	
+	// save max input report size and allocate space for the report
+	rc = usb_hid_init_report(hid_dev);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize input report buffer.\n");
+	}
+	
 	return rc;
 }
@@ -500,30 +548,35 @@
 	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
 	
-	int allocated = (hid_dev->input_report != NULL);
-	
-	if (!allocated
-	    || hid_dev->input_report_size < buffer_size) {
-		uint8_t *input_old = hid_dev->input_report;
-		uint8_t *input_new = (uint8_t *)malloc(buffer_size);
-		
-		if (input_new == NULL) {
-			usb_log_error("Failed to allocate space for input "
-			    "buffer. This event may not be reported\n");
-			memset(hid_dev->input_report, 0, 
-			    hid_dev->input_report_size);
-		} else {
-			memcpy(input_new, input_old, 
-			    hid_dev->input_report_size);
-			hid_dev->input_report = input_new;
-			if (allocated) {
-				free(input_old);
-			}
-			usb_hid_new_report();
-		}
-	}
+//	int allocated = (hid_dev->input_report != NULL);
+	assert(hid_dev->input_report != NULL);
+	usb_log_debug("Max input report size: %zu, buffer size: %zu\n",
+	    hid_dev->max_input_report_size, buffer_size);
+	assert(hid_dev->max_input_report_size >= buffer_size);
+	
+//	if (/*!allocated*/
+//	    /*|| *//*hid_dev->input_report_size < buffer_size*/) {
+//		uint8_t *input_old = hid_dev->input_report;
+//		uint8_t *input_new = (uint8_t *)malloc(buffer_size);
+		
+//		if (input_new == NULL) {
+//			usb_log_error("Failed to allocate space for input "
+//			    "buffer. This event may not be reported\n");
+//			memset(hid_dev->input_report, 0, 
+//			    hid_dev->input_report_size);
+//		} else {
+//			memcpy(input_new, input_old, 
+//			    hid_dev->input_report_size);
+//			hid_dev->input_report = input_new;
+//			if (allocated) {
+//				free(input_old);
+//			}
+//			usb_hid_new_report();
+//		}
+//	}
 	
 	/*! @todo This should probably be atomic. */
 	memcpy(hid_dev->input_report, buffer, buffer_size);
 	hid_dev->input_report_size = buffer_size;
+	usb_hid_new_report();
 	
 	bool cont = false;
Index: uspace/drv/usbhid/usbhid.h
===================================================================
--- uspace/drv/usbhid/usbhid.h	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/drv/usbhid/usbhid.h	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -98,4 +98,5 @@
 	
 	size_t input_report_size;
+	size_t max_input_report_size;
 } usb_hid_dev_t;
 
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/drv/Makefile	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -40,5 +40,6 @@
 	generic/remote_usb.c \
 	generic/remote_pci.c \
-	generic/remote_usbhc.c
+	generic/remote_usbhc.c \
+	generic/remote_usbhid.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -46,4 +46,6 @@
 #include "remote_pci.h"
 
+#include <stdio.h>
+
 static iface_dipatch_table_t remote_ifaces = {
 	.ifaces = {
@@ -60,4 +62,5 @@
 {
 	assert(is_valid_iface_idx(idx));
+	
 	return remote_ifaces.ifaces[idx];
 }
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/drv/generic/driver.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -405,5 +405,6 @@
 				/* The interface has not such method */
 				printf("%s: driver_connection_gen error - "
-				    "invalid interface method.", driver->name);
+				    "invalid interface method (%d).\n",
+				    driver->name, iface_method_idx);
 				async_answer_0(callid, ENOTSUP);
 				break;
Index: uspace/lib/drv/generic/remote_usbhid.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhid.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/drv/generic/remote_usbhid.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -36,4 +36,5 @@
 #include <errno.h>
 #include <assert.h>
+#include <stdio.h>
 
 #include "usbhid_iface.h"
@@ -42,4 +43,6 @@
 static void remote_usbhid_get_event_length(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhid_get_event(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhid_get_report_descriptor_length(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhid_get_report_descriptor(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 // static void remote_usbhid_(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 
@@ -47,5 +50,7 @@
 static remote_iface_func_ptr_t remote_usbhid_iface_ops [] = {
 	remote_usbhid_get_event_length,
-	remote_usbhid_get_event
+	remote_usbhid_get_event,
+	remote_usbhid_get_report_descriptor_length,
+	remote_usbhid_get_report_descriptor
 };
 
@@ -58,5 +63,5 @@
 };
 
-usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+//usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
 
 
@@ -64,20 +69,25 @@
     ipc_callid_t callid, ipc_call_t *call)
 {
+	printf("remote_usbhid_get_event_length()\n");
+	
 	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
 
 	if (!hid_iface->get_event_length) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int len = hid_iface->get_event_length(fun);
-	if (len == 0) {
-		len = EEMPTY;
-	}
-	if (len < 0) {
-		async_answer_0(callid, len);
-	} else {
-		async_answer_1(callid, EOK, len);
-	}
+		printf("Get event length not set!\n");
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t len = hid_iface->get_event_length(fun);
+//	if (len == 0) {
+//		len = EEMPTY;
+//	}
+	async_answer_1(callid, EOK, len);
+	
+//	if (len < 0) {
+//		async_answer_0(callid, len);
+//	} else {
+//		async_answer_1(callid, EOK, len);
+//	}
 }
 
@@ -100,43 +110,108 @@
 		return;
 	}
-	/* Check that length is even number. Truncate otherwise. */
-	if ((len % 2) == 1) {
-		len--;
-	}
+//	/* Check that length is even number. Truncate otherwise. */
+//	if ((len % 2) == 1) {
+//		len--;
+//	}
 	if (len == 0) {
 		async_answer_0(data_callid, EINVAL);
 		async_answer_0(callid, EINVAL);
+		return;
 	}
 
 	int rc;
 
-	size_t items = len / 2;
-	uint16_t *usage_pages_and_usages = malloc(sizeof(uint16_t) * len);
-	if (usage_pages_and_usages == NULL) {
+	uint8_t *data = malloc(len);
+	if (data == NULL) {
 		async_answer_0(data_callid, ENOMEM);
 		async_answer_0(callid, ENOMEM);
-	}
-
-	size_t act_items;
-	int rc = hid_iface->get_event(fun, usage_pages_and_usages,
-	    usage_pages_and_usages + items, items, &act_items, flags);
+		return;
+	}
+
+	size_t act_length;
+	rc = hid_iface->get_event(fun, data, len, &act_length, flags);
 	if (rc != EOK) {
-		free(usage_pages_and_usages);
+		free(data);
 		async_answer_0(data_callid, rc);
 		async_answer_0(callid, rc);
-	}
-	if (act_items >= items) {
+		return;
+	}
+	if (act_length >= len) {
 		/* This shall not happen. */
 		// FIXME: how about an assert here?
-		act_items = items;
-	}
-
-	async_data_read_finalize(data_callid, usage_pages_and_usages,
-	    act_items * 2 * sizeof(uint16_t));
-
-	free(usage_pages_and_usages);
+		act_length = len;
+	}
+
+	async_data_read_finalize(data_callid, data, act_length);
+
+	free(data);
 
 	async_answer_0(callid, EOK);
 }
+
+void remote_usbhid_get_report_descriptor_length(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
+
+	if (!hid_iface->get_report_descriptor_length) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t len = hid_iface->get_report_descriptor_length(fun);
+	async_answer_1(callid, EOK, (sysarg_t) len);
+}
+
+void remote_usbhid_get_report_descriptor(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
+
+	if (!hid_iface->get_report_descriptor) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t len;
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &len)) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (len == 0) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	uint8_t *descriptor = malloc(len);
+	if (descriptor == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	size_t act_len = 0;
+	int rc = hid_iface->get_report_descriptor(fun, descriptor, len,
+	    &act_len);
+	if (act_len > len) {
+		rc = ELIMIT;
+	}
+	if (rc != EOK) {
+		free(descriptor);
+		async_answer_0(data_callid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	async_data_read_finalize(data_callid, descriptor, act_len);
+	async_answer_0(callid, EOK);
+
+	free(descriptor);
+}
+
+
 
 /**
Index: uspace/lib/drv/include/remote_usbhid.h
===================================================================
--- uspace/lib/drv/include/remote_usbhid.h	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/drv/include/remote_usbhid.h	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -36,5 +36,5 @@
 #define LIBDRV_REMOTE_USBHID_H_
 
-remote_iface_t remote_usbhid_iface;
+extern remote_iface_t remote_usbhid_iface;
 
 #endif
Index: uspace/lib/drv/include/usbhid_iface.h
===================================================================
--- uspace/lib/drv/include/usbhid_iface.h	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/drv/include/usbhid_iface.h	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -45,7 +45,5 @@
 	 * Parameters: none
 	 * Answer:
-	 * - EOK (expected always as long as device support USB HID interface)
-	 * Parameters of the answer:
-	 * - number of items
+	 * - Size of one report in bytes.
 	 */
 	IPC_M_USBHID_GET_EVENT_LENGTH,
@@ -63,6 +61,29 @@
 	 * It is okay if the client requests less data. Extra data must
 	 * be truncated by the driver.
+	 *
+	 * @todo Change this comment.
 	 */
-	IPC_M_USBHID_GET_EVENT
+	IPC_M_USBHID_GET_EVENT,
+	
+	/** Get the size of the report descriptor from the HID device.
+	 *
+	 * Parameters:
+	 * - none
+	 * Answer:
+	 * - EOK - method is implemented (expected always)
+	 * Parameters of the answer:
+	 * - Size of the report in bytes.
+	 */
+	IPC_M_USBHID_GET_REPORT_DESCRIPTOR_LENGTH,
+	
+	/** Get the report descriptor from the HID device.
+	 *
+	 * Parameters:
+	 * - none
+	 * The call is followed by data read expecting the descriptor itself.
+	 * Answer:
+	 * - EOK - report descriptor returned.
+	 */
+	IPC_M_USBHID_GET_REPORT_DESCRIPTOR
 } usbhid_iface_funcs_t;
 
@@ -75,5 +96,5 @@
 	 *
 	 * @param[in] fun DDF function answering the request.
-	 * @return Number of events or error code.
+	 * @return Size of the event in bytes.
 	 */
 	size_t (*get_event_length)(ddf_fun_t *fun);
@@ -87,6 +108,24 @@
 	 * @return Error code.
 	 */
-	int (*get_event)(ddf_fun_t *fun, int32_t *buffer, size_t size,
+	int (*get_event)(ddf_fun_t *fun, uint8_t *buffer, size_t size,
 	    size_t *act_size, unsigned int flags);
+	
+	/** Get size of the report descriptor in bytes.
+	 *
+	 * @param[in] fun DDF function answering the request.
+	 * @return Size of the report descriptor in bytes.
+	 */
+	size_t (*get_report_descriptor_length)(ddf_fun_t *fun);
+	
+	/** Get the report descriptor from the HID device.
+	 *
+	 * @param[in] fun DDF function answering the request.
+	 * @param[out] desc Buffer with the report descriptor.
+	 * @param[in] size Size of the allocated @p desc buffer.
+	 * @param[out] act_size Actual size of the report descriptor returned.
+	 * @return Error code.
+	 */
+	int (*get_report_descriptor)(ddf_fun_t *fun, uint8_t *desc, 
+	    size_t size, size_t *act_size);
 } usbhid_iface_t;
 
Index: uspace/lib/usbhid/Makefile
===================================================================
--- uspace/lib/usbhid/Makefile	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/usbhid/Makefile	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -41,4 +41,5 @@
 	src/hidpath.c \
 	src/hidreport.c \
+	src/consumer.c \
 	src/hidreq.c
 
Index: uspace/lib/usbhid/include/usb/hid/hidreport.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidreport.h	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/usbhid/include/usb/hid/hidreport.h	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -44,6 +44,8 @@
  * report parser.
  *
- * \param dev USB device representing a HID device.
- * \param parser HID Report parser.
+ * \param[in] dev USB device representing a HID device.
+ * \param[in/out] parser HID Report parser.
+ * \param[out] report_desc Place to save report descriptor into.
+ * \param[out] report_size
  *
  * \retval EOK if successful.
@@ -57,5 +59,5 @@
  */
 int usb_hid_process_report_descriptor(usb_device_t *dev, 
-    usb_hid_report_t *report);
+    usb_hid_report_t *report, uint8_t **report_desc, size_t *report_size);
 
 #endif /* LIBUSB_HIDREPORT_H_ */
Index: uspace/lib/usbhid/include/usb/hid/iface.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/iface.h	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/usbhid/include/usb/hid/iface.h	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -38,7 +38,9 @@
 #include <sys/types.h>
 
-int usbhid_dev_get_event_length(int);
-int usbhid_dev_get_event(int, uint16_t *, uint16_t *, size_t, size_t *,
+int usbhid_dev_get_event_length(int, size_t *);
+int usbhid_dev_get_event(int, uint8_t *, size_t, size_t *,
     unsigned int);
+int usbhid_dev_get_report_descriptor_length(int, size_t *);
+int usbhid_dev_get_report_descriptor(int, uint8_t *, size_t, size_t *);
 
 #endif
Index: uspace/lib/usbhid/include/usb/hid/usages/consumer.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/usages/consumer.h	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
+++ uspace/lib/usbhid/include/usb/hid/usages/consumer.h	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -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 libusbhid
+ * @{
+ */
+/** @file
+ * USB multimedia key usage to string mapping.
+ */
+
+#ifndef LIBUSBHID_CONSUMER_H_
+#define LIBUSBHID_CONSUMER_H_
+
+const char *usbhid_multimedia_usage_to_str(int usage);
+
+#endif /* LIBUSBHID_CONSUMER_H_ */
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/consumer.c
===================================================================
--- uspace/lib/usbhid/src/consumer.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
+++ uspace/lib/usbhid/src/consumer.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -0,0 +1,732 @@
+/*
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * UUSB multimedia key usage, to string mapping.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/hid/usages/consumer.h>
+
+static const char *usbhid_consumer_usage_str[0x29d] = {
+	[0x01] = "Consumer Control",
+	[0x02] = "Numeric Key Pad",
+	[0x03] = "Programmable Buttons",
+	[0x04] = "Microphone",
+	[0x05] = "Headphone",
+	[0x06] = "Graphic Equalizer",
+	[0x07] = "Reserved",
+	[0x08] = "Reserved",
+	[0x09] = "Reserved",
+	[0x0a] = "Reserved",
+	[0x0b] = "Reserved",
+	[0x0c] = "Reserved",
+	[0x0d] = "Reserved",
+	[0x0e] = "Reserved",
+	[0x0f] = "Reserved",
+	[0x10] = "Reserved",
+	[0x11] = "Reserved",
+	[0x12] = "Reserved",
+	[0x13] = "Reserved",
+	[0x14] = "Reserved",
+	[0x15] = "Reserved",
+	[0x16] = "Reserved",
+	[0x17] = "Reserved",
+	[0x18] = "Reserved",
+	[0x19] = "Reserved",
+	[0x1a] = "Reserved",
+	[0x1b] = "Reserved",
+	[0x1c] = "Reserved",
+	[0x1d] = "Reserved",
+	[0x1e] = "Reserved",
+	[0x1f] = "Reserved",
+	[0x20] = "+10",
+	[0x21] = "+100",
+	[0x22] = "AM/PM",
+	[0x23] = "Reserved",
+	[0x24] = "Reserved",
+	[0x25] = "Reserved",
+	[0x26] = "Reserved",
+	[0x27] = "Reserved",
+	[0x28] = "Reserved",
+	[0x29] = "Reserved",
+	[0x2a] = "Reserved",
+	[0x2b] = "Reserved",
+	[0x2c] = "Reserved",
+	[0x2d] = "Reserved",
+	[0x2e] = "Reserved",
+	[0x2f] = "Reserved",
+	[0x30] = "Reserved",
+	[0x31] = "Reserved",
+	[0x32] = "Reserved",
+	[0x33] = "Reserved",
+	[0x34] = "Reserved",
+	[0x35] = "Reserved",
+	[0x36] = "Reserved",
+	[0x37] = "Reserved",
+	[0x38] = "Reserved",
+	[0x39] = "Reserved",
+	[0x3a] = "Reserved",
+	[0x3b] = "Reserved",
+	[0x3c] = "Reserved",
+	[0x3d] = "Reserved",
+	[0x3e] = "Reserved",
+	[0x3f] = "Reserved",
+	[0x40] = "Menu",
+	[0x41] = "Menu Pick",
+	[0x42] = "Menu Up",
+	[0x43] = "Menu Down",
+	[0x44] = "Menu Left",
+	[0x45] = "Menu Right",
+	[0x46] = "Menu Escape",
+	[0x47] = "Menu Value Increase",
+	[0x48] = "Menu Value Decrease",
+	[0x49] = "Reserved",
+	[0x4a] = "Reserved",
+	[0x4b] = "Reserved",
+	[0x4c] = "Reserved",
+	[0x4d] = "Reserved",
+	[0x4e] = "Reserved",
+	[0x4f] = "Reserved",
+	[0x50] = "Reserved",
+	[0x51] = "Reserved",
+	[0x52] = "Reserved",
+	[0x53] = "Reserved",
+	[0x54] = "Reserved",
+	[0x55] = "Reserved",
+	[0x56] = "Reserved",
+	[0x57] = "Reserved",
+	[0x58] = "Reserved",
+	[0x59] = "Reserved",
+	[0x5a] = "Reserved",
+	[0x5b] = "Reserved",
+	[0x5c] = "Reserved",
+	[0x5d] = "Reserved",
+	[0x5e] = "Reserved",
+	[0x5f] = "Reserved",
+	[0x60] = "Data On Screen",
+	[0x61] = "Closed Caption",
+	[0x62] = "Closed Caption Select",
+	[0x63] = "VCR/TV",
+	[0x64] = "Broadcast Mode",
+	[0x65] = "Snapshot",
+	[0x66] = "Still",
+	[0x67] = "Reserved",
+	[0x68] = "Reserved",
+	[0x69] = "Reserved",
+	[0x6a] = "Reserved",
+	[0x6b] = "Reserved",
+	[0x6c] = "Reserved",
+	[0x6d] = "Reserved",
+	[0x6e] = "Reserved",
+	[0x6f] = "Reserved",
+	[0x70] = "Reserved",
+	[0x71] = "Reserved",
+	[0x72] = "Reserved",
+	[0x73] = "Reserved",
+	[0x74] = "Reserved",
+	[0x75] = "Reserved",
+	[0x76] = "Reserved",
+	[0x77] = "Reserved",
+	[0x78] = "Reserved",
+	[0x79] = "Reserved",
+	[0x7a] = "Reserved",
+	[0x7b] = "Reserved",
+	[0x7c] = "Reserved",
+	[0x7d] = "Reserved",
+	[0x7e] = "Reserved",
+	[0x7f] = "Reserved",
+	[0x80] = "Selection",
+	[0x81] = "Assign Selection",
+	[0x82] = "Mode Step",
+	[0x83] = "Recall Last",
+	[0x84] = "Enter Channel",
+	[0x85] = "Order Movie",
+	[0x86] = "Channel",
+	[0x87] = "Media Selection",
+	[0x88] = "Media Select Computer",
+	[0x89] = "Media Select TV",
+	[0x8a] = "Media Select WWW",
+	[0x8b] = "Media Select DVD",
+	[0x8c] = "Media Select Telephone",
+	[0x8d] = "Media Select Program Guide",
+	[0x8e] = "Media Select Video Phone",
+	[0x8f] = "Media Select Games",
+	[0x90] = "Media Select Messages",
+	[0x91] = "Media Select CD",
+	[0x92] = "Media Select VCR",
+	[0x93] = "Media Select Tuner",
+	[0x94] = "Quit",
+	[0x95] = "Help",
+	[0x96] = "Media Select Tape",
+	[0x97] = "Media Select Cable",
+	[0x98] = "Media Select Satellite",
+	[0x99] = "Media Select Security",
+	[0x9a] = "Media Select Home",
+	[0x9b] = "Media Select Call",
+	[0x9c] = "Channel Increment",
+	[0x9d] = "Channel Decrement",
+	[0x9e] = "Media Select SAP",
+	[0x9f] = "Reserved",
+	[0xa0] = "VCR Plus",
+	[0xa1] = "Once",
+	[0xa2] = "Daily",
+	[0xa3] = "Weekly",
+	[0xa4] = "Monthly",
+	[0xa5] = "Reserved",
+	[0xa6] = "Reserved",
+	[0xa7] = "Reserved",
+	[0xa8] = "Reserved",
+	[0xa9] = "Reserved",
+	[0xaa] = "Reserved",
+	[0xab] = "Reserved",
+	[0xac] = "Reserved",
+	[0xad] = "Reserved",
+	[0xae] = "Reserved",
+	[0xaf] = "Reserved",
+	[0xb0] = "Play",
+	[0xb1] = "Pause",
+	[0xb2] = "Record",
+	[0xb3] = "Fast Forward",
+	[0xb4] = "Rewind",
+	[0xb5] = "Scan Next Track",
+	[0xb6] = "Scan Previous Trac",
+	[0xb7] = "Stop",
+	[0xb8] = "Eject",
+	[0xb9] = "Random Play",
+	[0xba] = "Select Disc",
+	[0xbb] = "Enter Disc",
+	[0xbc] = "Repeat",
+	[0xbd] = "Tracking",
+	[0xbe] = "Track Normal",
+	[0xbf] = "Slow Tracking",
+	[0xc0] = "Frame Forward",
+	[0xc1] = "Frame Back",
+	[0xc2] = "Mark",
+	[0xc3] = "Clear Mark",
+	[0xc4] = "Repeat From Mark",
+	[0xc5] = "Return to Mark",
+	[0xc6] = "Search Mark Forward",
+	[0xc7] = "Search Mark Backwards",
+	[0xc8] = "Counter Reset",
+	[0xc9] = "Show Counter",
+	[0xca] = "Tracking Increment",
+	[0xcb] = "Tracking Decrement",
+	[0xcc] = "Stop/Eject",
+	[0xcd] = "Play/Pause",
+	[0xce] = "Play/Skip",
+	[0xcf] = "Reserved",
+	[0xd0] = "Reserved",
+	[0xd1] = "Reserved",
+	[0xd2] = "Reserved",
+	[0xd3] = "Reserved",
+	[0xd4] = "Reserved",
+	[0xd5] = "Reserved",
+	[0xd6] = "Reserved",
+	[0xd7] = "Reserved",
+	[0xd8] = "Reserved",
+	[0xd9] = "Reserved",
+	[0xda] = "Reserved",
+	[0xdb] = "Reserved",
+	[0xdc] = "Reserved",
+	[0xdd] = "Reserved",
+	[0xde] = "Reserved",
+	[0xdf] = "Reserved",
+	[0xe0] = "Volume",
+	[0xe1] = "Balance",
+	[0xe2] = "Mute",
+	[0xe3] = "Bass",
+	[0xe4] = "Treble",
+	[0xe5] = "Bass Boost",
+	[0xe6] = "Surround Mode",
+	[0xe7] = "Loudness",
+	[0xe8] = "MPX",
+	[0xe9] = "Volume Increment",
+	[0xea] = "Volume Decrement",
+	[0xeb] = "Reserved",
+	[0xec] = "Reserved",
+	[0xed] = "Reserved",
+	[0xee] = "Reserved",
+	[0xef] = "Reserved",
+	[0xf0] = "Speed Select",
+	[0xf1] = "Playback Speed",
+	[0xf2] = "Standard Play",
+	[0xf3] = "Long Play",
+	[0xf4] = "Extended Play",
+	[0xf5] = "Slow",
+	[0xf6] = "Reserved",
+	[0xf7] = "Reserved",
+	[0xf8] = "Reserved",
+	[0xf9] = "Reserved",
+	[0xfa] = "Reserved",
+	[0xfb] = "Reserved",
+	[0xfc] = "Reserved",
+	[0xfd] = "Reserved",
+	[0xfe] = "Reserved",
+	[0xff] = "Reserved",
+	[0x100] = "Fan Enable",
+	[0x101] = "Fan Speed",
+	[0x102] = "Light Enable",
+	[0x103] = "Light Illumination Level",
+	[0x104] = "Climate Control Enable",
+	[0x105] = "Room Temperature",
+	[0x106] = "Security Enable",
+	[0x107] = "Fire Alarm",
+	[0x108] = "Police Alarm",
+	[0x109] = "Proximity",
+	[0x10a] = "Motion",
+	[0x10b] = "Duress Alarm",
+	[0x10c] = "Holdup Alarm",
+	[0x10d] = "Medical Alarm",
+	[0x10e] = "Reserved",
+	[0x10f] = "Reserved",
+	[0x110] = "Reserved",
+	[0x111] = "Reserved",
+	[0x112] = "Reserved",
+	[0x113] = "Reserved",
+	[0x114] = "Reserved",
+	[0x115] = "Reserved",
+	[0x116] = "Reserved",
+	[0x117] = "Reserved",
+	[0x118] = "Reserved",
+	[0x119] = "Reserved",
+	[0x11a] = "Reserved",
+	[0x11b] = "Reserved",
+	[0x11c] = "Reserved",
+	[0x11d] = "Reserved",
+	[0x11e] = "Reserved",
+	[0x11f] = "Reserved",
+	[0x120] = "Reserved", 
+	[0x121] = "Reserved",
+	[0x122] = "Reserved",
+	[0x123] = "Reserved",
+	[0x124] = "Reserved",
+	[0x125] = "Reserved",
+	[0x126] = "Reserved",
+	[0x127] = "Reserved",
+	[0x128] = "Reserved",
+	[0x129] = "Reserved",
+	[0x12a] = "Reserved",
+	[0x12b] = "Reserved",
+	[0x12c] = "Reserved",
+	[0x12d] = "Reserved",
+	[0x12e] = "Reserved",
+	[0x12f] = "Reserved",
+	[0x130] = "Reserved", 
+	[0x131] = "Reserved",
+	[0x132] = "Reserved",
+	[0x133] = "Reserved",
+	[0x134] = "Reserved",
+	[0x135] = "Reserved",
+	[0x136] = "Reserved",
+	[0x137] = "Reserved",
+	[0x138] = "Reserved",
+	[0x139] = "Reserved",
+	[0x13a] = "Reserved",
+	[0x13b] = "Reserved",
+	[0x13c] = "Reserved",
+	[0x13d] = "Reserved",
+	[0x13e] = "Reserved",
+	[0x13f] = "Reserved",
+	[0x140] = "Reserved", 
+	[0x141] = "Reserved",
+	[0x142] = "Reserved",
+	[0x143] = "Reserved",
+	[0x144] = "Reserved",
+	[0x145] = "Reserved",
+	[0x146] = "Reserved",
+	[0x147] = "Reserved",
+	[0x148] = "Reserved",
+	[0x149] = "Reserved",
+	[0x14a] = "Reserved",
+	[0x14b] = "Reserved",
+	[0x14c] = "Reserved",
+	[0x14d] = "Reserved",
+	[0x14e] = "Reserved",
+	[0x14f] = "Reserved",
+	[0x150] = "Balance Right",
+	[0x151] = "Balance Left",
+	[0x152] = "Bass Increment",
+	[0x153] = "Bass Decrement",
+	[0x154] = "Treble Increment",
+	[0x155] = "Treble Decrement",
+	[0x156] = "Reserved",
+	[0x157] = "Reserved",
+	[0x158] = "Reserved",
+	[0x159] = "Reserved",
+	[0x15a] = "Reserved",
+	[0x15b] = "Reserved",
+	[0x15c] = "Reserved",
+	[0x15d] = "Reserved",
+	[0x15e] = "Reserved",
+	[0x15f] = "Reserved",
+	[0x160] = "Speaker System",
+	[0x161] = "Channel Left",
+	[0x162] = "Channel Right",
+	[0x163] = "Channel Center",
+	[0x164] = "Channel Front",
+	[0x165] = "Channel Center Front",
+	[0x166] = "Channel Side",
+	[0x167] = "Channel Surround",
+	[0x168] = "Channel Low Frequency Enhancement",
+	[0x169] = "Channel Top",
+	[0x16a] = "Channel Unknown",
+	[0x16b] = "Reserved",
+	[0x16c] = "Reserved",
+	[0x16d] = "Reserved",
+	[0x16e] = "Reserved",
+	[0x16f] = "Reserved",
+	[0x170] = "Sub-channel",
+	[0x171] = "Sub-channel Increment",
+	[0x172] = "Sub-channel Decrement",
+	[0x173] = "Alternate Audio Increment",
+	[0x174] = "Alternate Audio Decrement",
+	[0x175] = "Reserved",
+	[0x176] = "Reserved",
+	[0x177] = "Reserved",
+	[0x178] = "Reserved",
+	[0x179] = "Reserved",
+	[0x17a] = "Reserved",
+	[0x17b] = "Reserved",
+	[0x17c] = "Reserved",
+	[0x17d] = "Reserved",
+	[0x17e] = "Reserved",
+	[0x17f] = "Reserved",
+	[0x180] = "Application Launch Buttons",
+	[0x181] = "AL Launch Buttion Configuration Tool",
+	[0x182] = "AL Programmable Button Configuration",
+	[0x183] = "AL Consumer Control Configuration",
+	[0x184] = "AL Word Processor",
+	[0x185] = "AL Text Editor",
+	[0x186] = "AL Spreadsheet",
+	[0x187] = "AL Graphics Editor",
+	[0x188] = "AL Presentation App",
+	[0x189] = "AL Database App",
+	[0x18a] = "AL Email Reader",
+	[0x18b] = "AL Newsreader",
+	[0x18c] = "AL Voicemail",
+	[0x18d] = "AL Contacts/Address Book",
+	[0x18e] = "AL Calendar/Schedule",
+	[0x18f] = "AL Task/Project Manager",
+	[0x190] = "AL Log/Journal/Timecard",
+	[0x191] = "AL Checkbook/Finance",
+	[0x192] = "AL Calculator",
+	[0x193] = "AL A/V Capture/Playback",
+	[0x194] = "AL Local Machine Browser",
+	[0x195] = "AL LAN/WAN Browser",
+	[0x196] = "AL Internet Browser",
+	[0x197] = "AL Remote Networking/ISP Connect",
+	[0x198] = "AL Network Conference",
+	[0x199] = "AL Network Chat",
+	[0x19a] = "AL Telephony/Dialer",
+	[0x19b] = "AL Logon",
+	[0x19c] = "AL Logoff",
+	[0x19d] = "AL Logon/Logoff",
+	[0x19e] = "AL Terminal Lock/Screensaver",
+	[0x19f] = "AL Control Panel",
+	[0x1a0] = "AL Command Line Processor/Run",
+	[0x1a1] = "AL Process/Task Manager",
+	[0x1a2] = "AL Select Task/Application",
+	[0x1a3] = "AL Next Task/Application",
+	[0x1a4] = "AL Previous Task/Application",
+	[0x1a5] = "AL Preemptive Halt Task/Application",
+	[0x1a6] = "AL Integrated Help Center",
+	[0x1a7] = "AL Documents",
+	[0x1a8] = "AL Thesaurus",
+	[0x1a9] = "AL Dictionary",
+	[0x1aa] = "AL Desktop",
+	[0x1ab] = "AL Spell Check",
+	[0x1ac] = "AL Grammar Check",
+	[0x1ad] = "AL Wireless Status",
+	[0x1ae] = "AL Keyboard Layout",
+	[0x1af] = "AL Virus Protection",
+	[0x1b0] = "AL Encryption",
+	[0x1b1] = "AL Screen Saver",
+	[0x1b2] = "AL Alarms",
+	[0x1b3] = "AL Clock",
+	[0x1b4] = "AL File Browser",
+	[0x1b5] = "AL Power Status",
+	[0x1b6] = "AL Image Browser",
+	[0x1b7] = "AL Audio Browser",
+	[0x1b8] = "AL Movie Browser",
+	[0x1b9] = "AL Digital Rights Manager",
+	[0x1ba] = "AL Digital Wallet",
+	[0x1bb] = "Reserved",
+	[0x1bc] = "AL Instant Messaging",
+	[0x1bd] = "AL OEM Features Tips/Tutorial Browser",
+	[0x1be] = "AL OEM Help",
+	[0x1bf] = "AL Online Community",
+	[0x1c0] = "AL Entertainment Content Browser",
+	[0x1c1] = "AL Online Shopping Browser",
+	[0x1c2] = "AL SmartCard Information/Help",
+	[0x1c3] = "AL Market Monitor/Finance Browser",
+	[0x1c4] = "AL Customized Corporate News Browser",
+	[0x1c5] = "AL Online Activity Browser",
+	[0x1c6] = "AL Research/Search Browser",
+	[0x1c7] = "AL Audio Player",
+	[0x1c8] = "Reserved",
+	[0x1c9] = "Reserved",
+	[0x1ca] = "Reserved",
+	[0x1cb] = "Reserved",
+	[0x1cc] = "Reserved",
+	[0x1cd] = "Reserved",
+	[0x1ce] = "Reserved",
+	[0x1cf] = "Reserved",
+	[0x1d0] = "Reserved",
+	[0x1d1] = "Reserved",
+	[0x1d2] = "Reserved",
+	[0x1d3] = "Reserved",
+	[0x1d4] = "Reserved",
+	[0x1d5] = "Reserved",
+	[0x1d6] = "Reserved",
+	[0x1d7] = "Reserved",
+	[0x1d8] = "Reserved",
+	[0x1d9] = "Reserved",
+	[0x1da] = "Reserved",
+	[0x1db] = "Reserved",
+	[0x1dc] = "Reserved",
+	[0x1dd] = "Reserved",
+	[0x1de] = "Reserved",
+	[0x1df] = "Reserved",
+	[0x1e0] = "Reserved",
+	[0x1e1] = "Reserved",
+	[0x1e2] = "Reserved",
+	[0x1e3] = "Reserved",
+	[0x1e4] = "Reserved",
+	[0x1e5] = "Reserved",
+	[0x1e6] = "Reserved",
+	[0x1e7] = "Reserved",
+	[0x1e8] = "Reserved",
+	[0x1e9] = "Reserved",
+	[0x1ea] = "Reserved",
+	[0x1eb] = "Reserved",
+	[0x1ec] = "Reserved",
+	[0x1ed] = "Reserved",
+	[0x1ee] = "Reserved",
+	[0x1ef] = "Reserved",
+	[0x1f0] = "Reserved",
+	[0x1f1] = "Reserved",
+	[0x1f2] = "Reserved",
+	[0x1f3] = "Reserved",
+	[0x1f4] = "Reserved",
+	[0x1f5] = "Reserved",
+	[0x1f6] = "Reserved",
+	[0x1f7] = "Reserved",
+	[0x1f8] = "Reserved",
+	[0x1f9] = "Reserved",
+	[0x1fa] = "Reserved",
+	[0x1fb] = "Reserved",
+	[0x1fc] = "Reserved",
+	[0x1fd] = "Reserved",
+	[0x1fe] = "Reserved",
+	[0x1ff] = "Reserved",
+	[0x200] = "Generic GUI Application Controls",
+	[0x201] = "AC New",
+	[0x202] = "AC Open",
+	[0x203] = "AC Close",
+	[0x204] = "AC Exit",
+	[0x205] = "AC Maximize",
+	[0x206] = "AC Minimize",
+	[0x207] = "AC Save",
+	[0x208] = "AC Print",
+	[0x209] = "AC Properties",
+	[0x20a] = "",
+	[0x20b] = "",
+	[0x20c] = "",
+	[0x20d] = "",
+	[0x20e] = "",
+	[0x20f] = "",
+	[0x210] = "",
+	[0x211] = "",
+	[0x212] = "",
+	[0x213] = "",
+	[0x214] = "",
+	[0x215] = "",
+	[0x216] = "",
+	[0x217] = "",
+	[0x218] = "",
+	[0x219] = "",
+	[0x21a] = "AC Undo",
+	[0x21b] = "AC Copy",
+	[0x21c] = "AC Cut",
+	[0x21d] = "AC Paste",
+	[0x21e] = "AC Select All",
+	[0x21f] = "AC Find",
+	[0x220] = "AC Find and Replace",
+	[0x221] = "AC Search",
+	[0x222] = "AC Go To",
+	[0x223] = "AC Home",
+	[0x224] = "AC Back",
+	[0x225] = "AC Forward",
+	[0x226] = "AC Stop",
+	[0x227] = "AC Refresh",
+	[0x228] = "AC Previous Link",
+	[0x229] = "AC Next Link",
+	[0x22a] = "AC Bookmarks",
+	[0x22b] = "AC History",
+	[0x22c] = "AC Subscriptions",
+	[0x22d] = "AC Zoom In",
+	[0x22e] = "AC Zoom Out",
+	[0x22f] = "AC Zoom",
+	[0x230] = "AC Full Screen View",
+	[0x231] = "AC Normal View",
+	[0x232] = "AC View Toggle",
+	[0x233] = "AC Scroll Up",
+	[0x234] = "AC Scroll Down",
+	[0x235] = "AC Scroll",
+	[0x236] = "AC Pan Left",
+	[0x237] = "AC Pan Right",
+	[0x238] = "AC Pan",
+	[0x239] = "AC New Window",
+	[0x23a] = "AC Tile Horizontally",
+	[0x23b] = "AC Tile Vertically",
+	[0x23c] = "AC Format",
+	[0x23d] = "AC Edit",
+	[0x23e] = "AC Bold",
+	[0x23f] = "AC Italics",
+	[0x240] = "AC Undeline",
+	[0x241] = "AC Strikethrough",
+	[0x242] = "AC Subscript",
+	[0x243] = "AC Superscript",
+	[0x244] = "AC All Caps",
+	[0x245] = "AC Rotate",
+	[0x246] = "AC Resize",
+	[0x247] = "AC Flip Horizontal",
+	[0x248] = "AC Flip Vertical",
+	[0x249] = "AC Mirror Horizontal",
+	[0x24a] = "AC Mirror Vertical",
+	[0x24b] = "AC Font Select",
+	[0x24c] = "AC Font Color",
+	[0x24d] = "AC Font Size",
+	[0x24e] = "AC Justify Left",
+	[0x24f] = "AC Justify Center H",
+	[0x250] = "AC Justify Right",
+	[0x251] = "AC Justify Block H",
+	[0x252] = "AC Justify Top",
+	[0x253] = "AC Justify Center V",
+	[0x254] = "AC Justify Bottom",
+	[0x255] = "AC Justify Block V",
+	[0x256] = "AC Indent Decrease",
+	[0x257] = "AC Indent Increase",
+	[0x258] = "AC Numbered List",
+	[0x259] = "AC Restart Numbering",
+	[0x25a] = "AC Bulleted List",
+	[0x25b] = "AC Promote",
+	[0x25c] = "AC Demote",
+	[0x25d] = "AC Yes",
+	[0x25e] = "AC No",
+	[0x25f] = "AC Cancel",
+	[0x260] = "AC Catalog",
+	[0x261] = "AC Buy/Checkout",
+	[0x262] = "AC Add to Cart",
+	[0x263] = "AC Expand",
+	[0x264] = "AC Expand All",
+	[0x265] = "AC Collapse",
+	[0x266] = "AC Collapse All",
+	[0x267] = "AC Print Preview",
+	[0x268] = "AC Paste Special",
+	[0x269] = "AC Insert Mode",
+	[0x26a] = "AC Delete",
+	[0x26b] = "AC Lock",
+	[0x26c] = "AC Unlock",
+	[0x26d] = "AC Protect",
+	[0x26e] = "AC Unprotect",
+	[0x26f] = "AC Attach Comment",
+	[0x270] = "AC Delete Comment",
+	[0x271] = "AC View Comment",
+	[0x272] = "AC Select Word",
+	[0x273] = "AC Select Sentence",
+	[0x274] = "AC Select Paragraph",
+	[0x275] = "AC Select Column",
+	[0x276] = "AC Select Row",
+	[0x277] = "AC Select Table",
+	[0x278] = "AC Select Object",
+	[0x279] = "AC Redo/Repeat",
+	[0x27a] = "AC Sort",
+	[0x27b] = "AC Sort Ascending",
+	[0x27c] = "AC Sort Descending",
+	[0x27d] = "AC Filter",
+	[0x27e] = "AC Set Clock",
+	[0x27f] = "AC View Clock",
+	[0x280] = "AC Select Time Zone",
+	[0x281] = "AC Edit Time Zones",
+	[0x282] = "AC Set Alarm",
+	[0x283] = "AC Clear Alarm",
+	[0x284] = "AC Snooze Alarm",
+	[0x285] = "AC Reset Alarm",
+	[0x286] = "AC Synchronize",
+	[0x287] = "AC Send/Receive",
+	[0x288] = "AC Send To",
+	[0x289] = "AC Reply",
+	[0x28a] = "AC Reply All",
+	[0x28b] = "AC Forward Msg",
+	[0x28c] = "AC Send",
+	[0x28d] = "AC Attach File",
+	[0x28e] = "AC Upload",
+	[0x28f] = "AC Download (Save Target As)",
+	[0x290] = "AC Set Borders",
+	[0x291] = "AC Insert Row",
+	[0x292] = "AC Insert Column",
+	[0x293] = "AC Insert File",
+	[0x294] = "AC Insert Picture",
+	[0x295] = "AC Insert Object",
+	[0x296] = "AC Insert Symbol",
+	[0x297] = "AC Save and Close",
+	[0x298] = "AC Rename",
+	[0x299] = "AC Merge",
+	[0x29a] = "AC Split",
+	[0x29b] = "AC Distrubute Horizontally",
+	[0x29c] = "AC Distrubute Vertically"
+};
+
+/**
+ * Translates USB HID Usages from the Consumer Page into their string 
+ * representation.
+ *
+ * @param usage USB HID Consumer Page Usage number.
+ * 
+ * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
+ */
+const char *usbhid_multimedia_usage_to_str(int usage)
+{
+	size_t map_length = sizeof(usbhid_consumer_usage_str) / sizeof(char *);
+
+	if ((usage < 0) || ((size_t)usage >= map_length))
+		return "Unknown usage";
+
+	/*! @todo What if the usage is not in the table? */
+	return usbhid_consumer_usage_str[usage];
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/hidiface.c
===================================================================
--- uspace/lib/usbhid/src/hidiface.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/usbhid/src/hidiface.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -46,5 +46,5 @@
  * @return Number of usages returned or negative error code.
  */
-int usbhid_dev_get_event_length(int dev_phone)
+int usbhid_dev_get_event_length(int dev_phone, size_t *size)
 {
 	if (dev_phone < 0) {
@@ -56,8 +56,10 @@
 	    IPC_M_USBHID_GET_EVENT_LENGTH, &len);
 	if (rc == EOK) {
-		return (int) len;
-	} else {
-		return rc;
-	}
+		if (size != NULL) {
+			*size = (size_t) len;
+		}
+	}
+	
+	return rc;
 }
 
@@ -74,19 +76,23 @@
  * @return Error code.
  */
-int usbhid_dev_get_event(int dev_phone, uint16_t *usage_pages, uint16_t *usages,
-    size_t usage_count, size_t *actual_usage_count, unsigned int flags)
-{
-	if (dev_phone < 0) {
-		return EINVAL;
-	}
-	if ((usage_pages == NULL) || (usages == NULL)) {
-		return ENOMEM;
-	}
-	if (usage_count == 0) {
-		return EINVAL;
-	}
-
-	size_t buffer_size = sizeof(uint16_t) * usage_count * 2;
-	uint16_t *buffer = malloc(buffer_size);
+int usbhid_dev_get_event(int dev_phone, uint8_t *buf, 
+    size_t size, size_t *actual_size, unsigned int flags)
+{
+	if (dev_phone < 0) {
+		return EINVAL;
+	}
+	if ((buf == NULL)) {
+		return ENOMEM;
+	}
+	if (size == 0) {
+		return EINVAL;
+	}
+	
+//	if (size == 0) {
+//		return EOK;
+//	}
+
+	size_t buffer_size =  size;
+	uint8_t *buffer = malloc(buffer_size);
 	if (buffer == NULL) {
 		return ENOMEM;
@@ -128,13 +134,85 @@
 	}
 
-	size_t actual_size = IPC_GET_ARG2(data_request_call);
-	size_t items = actual_size / 2;
+	size_t act_size = IPC_GET_ARG2(data_request_call);
 
 	/* Copy the individual items. */
-	memcpy(usage_pages, buffer, items * sizeof(uint16_t));
-	memcpy(usages, buffer + items, items * sizeof(uint16_t));
-
-	if (actual_usage_count != NULL) {
-		*actual_usage_count = items;
+	memcpy(buf, buffer, act_size);
+//	memcpy(usages, buffer + items, items * sizeof(int32_t));
+
+	if (actual_size != NULL) {
+		*actual_size = act_size;
+	}
+
+	return EOK;
+}
+
+
+int usbhid_dev_get_report_descriptor_length(int dev_phone, size_t *size)
+{
+	if (dev_phone < 0) {
+		return EINVAL;
+	}
+
+	sysarg_t arg_size;
+	int rc = async_req_1_1(dev_phone, DEV_IFACE_ID(USBHID_DEV_IFACE),
+	    IPC_M_USBHID_GET_REPORT_DESCRIPTOR_LENGTH, &arg_size);
+	if (rc == EOK) {
+		if (size != NULL) {
+			*size = (size_t) arg_size;
+		}
+	}
+	return rc;
+}
+
+int usbhid_dev_get_report_descriptor(int dev_phone, uint8_t *buf, size_t size, 
+    size_t *actual_size)
+{
+	if (dev_phone < 0) {
+		return EINVAL;
+	}
+	if ((buf == NULL)) {
+		return ENOMEM;
+	}
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	aid_t opening_request = async_send_1(dev_phone,
+	    DEV_IFACE_ID(USBHID_DEV_IFACE), IPC_M_USBHID_GET_REPORT_DESCRIPTOR,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(dev_phone, buf, size,
+	    &data_request_call);
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		/* Prefer return code of the opening request. */
+		if (opening_request_rc != EOK) {
+			return (int) opening_request_rc;
+		} else {
+			return (int) data_request_rc;
+		}
+	}
+
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	size_t act_size = IPC_GET_ARG2(data_request_call);
+
+	if (actual_size != NULL) {
+		*actual_size = act_size;
 	}
 
Index: uspace/lib/usbhid/src/hidreport.c
===================================================================
--- uspace/lib/usbhid/src/hidreport.c	(revision 14e1bcc46c8957d6c1c7726e8185e23d95ae25be)
+++ uspace/lib/usbhid/src/hidreport.c	(revision 3e6e2b91b548e7ef0d65a32ef82e0fd714ebf15b)
@@ -164,5 +164,5 @@
 
 int usb_hid_process_report_descriptor(usb_device_t *dev, 
-    usb_hid_report_t *report)
+    usb_hid_report_t *report, uint8_t **report_desc, size_t *report_size)
 {
 	if (dev == NULL || report == NULL) {
@@ -172,31 +172,31 @@
 	}
 	
-	uint8_t *report_desc = NULL;
-	size_t report_size;
-	
-	int rc = usb_hid_get_report_descriptor(dev, &report_desc, 
-	    &report_size);
+//	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);
+		if (*report_desc != NULL) {
+			free(*report_desc);
+			*report_desc = NULL;
 		}
 		return rc;
 	}
 	
-	assert(report_desc != NULL);
-	
-	rc = usb_hid_parse_report_descriptor(report, report_desc, report_size);
+	assert(*report_desc != NULL);
+	
+	rc = usb_hid_parse_report_descriptor(report, *report_desc, *report_size);
 	if (rc != EOK) {
 		usb_log_error("Problem parsing Report descriptor: %s.\n",
 		    str_error(rc));
-		free(report_desc);
+		free(*report_desc);
+		*report_desc = NULL;
 		return rc;
 	}
 	
 	usb_hid_descriptor_print(report);
-	free(report_desc);
 	
 	return EOK;
