Index: uspace/drv/usbhid/Makefile
===================================================================
--- uspace/drv/usbhid/Makefile	(revision cecb1a97a6e0426692efc40b5e2673c2b7ad6200)
+++ uspace/drv/usbhid/Makefile	(revision d3b6d5e0a18004858a874fcb193bd53440e9a57d)
@@ -46,6 +46,6 @@
 	generic/hiddev.c \
 	mouse/mousedev.c \
-	lgtch-ultrax/lgtch-ultrax.c \
-	lgtch-ultrax/keymap.c \
+	multimedia/multimedia.c \
+	multimedia/keymap.c \
 	$(STOLEN_LAYOUT_SOURCES)
 
Index: pace/drv/usbhid/lgtch-ultrax/keymap.c
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/keymap.c	(revision cecb1a97a6e0426692efc40b5e2673c2b7ad6200)
+++ 	(revision )
@@ -1,101 +1,0 @@
-/*
- * 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: pace/drv/usbhid/lgtch-ultrax/keymap.h
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/keymap.h	(revision cecb1a97a6e0426692efc40b5e2673c2b7ad6200)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * 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: pace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision cecb1a97a6e0426692efc40b5e2673c2b7ad6200)
+++ 	(revision )
@@ -1,427 +1,0 @@
-/*
- * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
- * 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 Logitech UltraX Keyboard sample driver.
- */
-
-
-#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"
-
-typedef enum usb_lgtch_flags {
-	USB_LGTCH_STATUS_UNINITIALIZED = 0,
-	USB_LGTCH_STATUS_INITIALIZED = 1,
-	USB_LGTCH_STATUS_TO_DESTROY = -1
-} usb_lgtch_flags;
-
-/*----------------------------------------------------------------------------*/
-/**
- * Logitech UltraX device type.
- */
-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;
-
-
-/*----------------------------------------------------------------------------*/
-/** 
- * 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);
-
-//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;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_lgtch_create_function(usb_hid_dev_t *hid_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;
-	}
-	
-	/*
-	 * 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
-	
-	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);
-		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);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-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;
-	
-	lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
-	usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
-	
-	int rc = usb_lgtch_create_function(hid_dev);
-	if (rc != EOK) {
-		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;
-//		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-bool usb_lgtch_polling_callback(struct usb_hid_dev *hid_dev, 
-    uint8_t *buffer, size_t buffer_size)
-{
-	// TODO: checks
-	
-	usb_log_debug(NAME " usb_lgtch_polling_callback(%p, %p, %zu)\n",
-	    hid_dev, buffer, buffer_size);
-
-	usb_log_debug(NAME " Calling usb_hid_parse_report() with "
-	    "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0));
-	
-	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, 0xc, 0);
-
-	uint8_t report_id;
-	
-	int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 
-	    &report_id);
-	
-	if (rc != EOK) {
-		usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n", 
-		    str_error(rc));
-		return true;
-	}
-	
-	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);
-	
-	return true;
-}
-
-/**
- * @}
- */
Index: pace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h	(revision cecb1a97a6e0426692efc40b5e2673c2b7ad6200)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * 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 Logitech UltraX Keyboard sample driver.
- */
-
-#ifndef USB_HID_LGTCH_ULTRAX_H_
-#define USB_HID_LGTCH_ULTRAX_H_
-
-#include <usb/devdrv.h>
-
-struct usb_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,
-    size_t buffer_size);
-
-/*----------------------------------------------------------------------------*/
-
-#endif // USB_HID_LGTCH_ULTRAX_H_
-
-/**
- * @}
- */
Index: uspace/drv/usbhid/multimedia/keymap.c
===================================================================
--- uspace/drv/usbhid/multimedia/keymap.c	(revision d3b6d5e0a18004858a874fcb193bd53440e9a57d)
+++ uspace/drv/usbhid/multimedia/keymap.c	(revision d3b6d5e0a18004858a874fcb193bd53440e9a57d)
@@ -0,0 +1,791 @@
+/*
+ * 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_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 */
+	[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 */
+};
+
+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"
+};
+
+/**
+ * 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_multimedia_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;
+}
+
+/**
+ * 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 d3b6d5e0a18004858a874fcb193bd53440e9a57d)
+++ uspace/drv/usbhid/multimedia/keymap.h	(revision d3b6d5e0a18004858a874fcb193bd53440e9a57d)
@@ -0,0 +1,47 @@
+/*
+ * 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_MULTIMEDIA_KEYMAP_H_
+#define USB_HID_MULTIMEDIA_KEYMAP_H_
+
+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 d3b6d5e0a18004858a874fcb193bd53440e9a57d)
+++ uspace/drv/usbhid/multimedia/multimedia.c	(revision d3b6d5e0a18004858a874fcb193bd53440e9a57d)
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak, Vojtech Horky
+ * 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 Keyboard multimedia keys subdriver.
+ */
+
+
+#include "multimedia.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 "multimedia-keys"
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Logitech UltraX device type.
+ */
+typedef struct usb_multimedia_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;
+} usb_multimedia_t;
+
+
+/*----------------------------------------------------------------------------*/
+/** 
+ * 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_multimedia_t *multim_dev = (usb_multimedia_t *)hid_dev->data;
+
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (multim_dev->console_phone != -1) {
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		multim_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 multimedia_ops = {
+	.default_handler = default_connection_handler
+};
+
+/*----------------------------------------------------------------------------*/
+/**
+ * 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_multimedia_push_ev(usb_hid_dev_t *hid_dev, int type, 
+    unsigned int key)
+{
+	assert(hid_dev != NULL);
+	assert(hid_dev->data != NULL);
+	
+	usb_multimedia_t *multim_dev = (usb_multimedia_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 (multim_dev->console_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
+	
+	async_msg_4(multim_dev->console_phone, KBD_EVENT, ev.type, ev.key, 
+	    ev.mods, ev.c);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_multimedia_free(usb_multimedia_t **multim_dev)
+{
+	if (multim_dev == NULL || *multim_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_hangup((*multim_dev)->console_phone);
+	
+	// free all buffers
+	if ((*multim_dev)->keys != NULL) {
+		free((*multim_dev)->keys);
+	}
+	if ((*multim_dev)->keys_old != NULL) {
+		free((*multim_dev)->keys_old);
+	}
+
+	free(*multim_dev);
+	*multim_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_multimedia_create_function(usb_hid_dev_t *hid_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;
+	}
+	
+	/*
+	 * Store the initialized HID device and HID ops
+	 * to the DDF function.
+	 */
+	fun->ops = &multimedia_ops;
+	fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
+	
+	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);
+		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);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_multimedia_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/multimedia structure...\n");
+	
+	usb_multimedia_t *multim_dev = (usb_multimedia_t *)malloc(
+	    sizeof(usb_multimedia_t));
+	if (multim_dev == NULL) {
+		return ENOMEM;
+	}
+	
+	multim_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);
+	
+	multim_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", 
+	    multim_dev->key_count);
+	
+	multim_dev->keys = (int32_t *)calloc(multim_dev->key_count, 
+	    sizeof(int32_t));
+	
+	if (multim_dev->keys == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(multim_dev);
+		return ENOMEM;
+	}
+	
+	multim_dev->keys_old = 
+		(int32_t *)calloc(multim_dev->key_count, sizeof(int32_t));
+	
+	if (multim_dev->keys_old == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(multim_dev->keys);
+		free(multim_dev);
+		return ENOMEM;
+	}
+	
+	/*! @todo Autorepeat */
+	
+	// save the KBD device structure into the HID device structure
+	hid_dev->data = multim_dev;
+	
+	usb_log_debug(NAME " HID/multimedia device structure initialized.\n");
+	
+	int rc = usb_multimedia_create_function(hid_dev);
+	if (rc != EOK) {
+		usb_multimedia_free(&multim_dev);
+		return rc;
+	}
+	
+	usb_log_debug(NAME " HID/multimedia structure initialized.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_multimedia_deinit(struct usb_hid_dev *hid_dev)
+{
+	if (hid_dev == NULL) {
+		return;
+	}
+	
+	if (hid_dev->data != NULL) {
+		usb_multimedia_t *multim_dev = 
+		    (usb_multimedia_t *)hid_dev->data;
+		usb_multimedia_free(&multim_dev);
+		hid_dev->data = NULL;
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, 
+    uint8_t *buffer, size_t buffer_size)
+{
+	// TODO: checks
+	
+	usb_log_debug(NAME " usb_lgtch_polling_callback(%p, %p, %zu)\n",
+	    hid_dev, buffer, buffer_size);
+
+	usb_log_debug(NAME " Calling usb_hid_parse_report() with "
+	    "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0));
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
+
+	uint8_t report_id;
+	
+	int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 
+	    &report_id);
+	
+	if (rc != EOK) {
+		usb_log_warning(NAME "Error in usb_hid_parse_report(): %s\n", 
+		    str_error(rc));
+		return true;
+	}
+	
+	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_multimedia_map_usage(field->usage);
+		const char *key_str = usb_multimedia_usage_to_str(field->usage);
+		usb_log_info("Pressed key: %s\n", key_str);
+		usb_multimedia_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);
+	
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/multimedia/multimedia.h
===================================================================
--- uspace/drv/usbhid/multimedia/multimedia.h	(revision d3b6d5e0a18004858a874fcb193bd53440e9a57d)
+++ uspace/drv/usbhid/multimedia/multimedia.h	(revision d3b6d5e0a18004858a874fcb193bd53440e9a57d)
@@ -0,0 +1,58 @@
+/*
+ * 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 Keyboard multimedia keys subdriver.
+ */
+
+#ifndef USB_HID_MULTIMEDIA_H_
+#define USB_HID_MULTIMEDIA_H_
+
+#include <usb/devdrv.h>
+
+struct usb_hid_dev;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_multimedia_init(struct usb_hid_dev *hid_dev);
+
+void usb_multimedia_deinit(struct usb_hid_dev *hid_dev);
+
+bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, 
+    uint8_t *buffer, size_t buffer_size);
+
+/*----------------------------------------------------------------------------*/
+
+#endif // USB_HID_MULTIMEDIA_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/subdrivers.c
===================================================================
--- uspace/drv/usbhid/subdrivers.c	(revision cecb1a97a6e0426692efc40b5e2673c2b7ad6200)
+++ uspace/drv/usbhid/subdrivers.c	(revision d3b6d5e0a18004858a874fcb193bd53440e9a57d)
@@ -38,5 +38,6 @@
 #include "usb/classes/hidpath.h"
 
-#include "lgtch-ultrax/lgtch-ultrax.h"
+//#include "lgtch-ultrax/lgtch-ultrax.h"
+#include "multimedia/multimedia.h"
 #include "mouse/mousedev.h"
 
@@ -79,7 +80,7 @@
 		-1,
 		{
-			.init = usb_lgtch_init,
-			.deinit = usb_lgtch_deinit,
-			.poll = usb_lgtch_polling_callback,
+			.init = usb_multimedia_init,
+			.deinit = usb_multimedia_deinit,
+			.poll = usb_multimedia_polling_callback,
 			.poll_end = NULL
 		}
