Index: uspace/drv/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/usbhid/generic/hiddev.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/generic/hiddev.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -37,4 +37,8 @@
 #include <usb/debug.h>
 #include <usb/classes/classes.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usbhid_iface.h>
 
 #include "hiddev.h"
@@ -55,4 +59,99 @@
 /*----------------------------------------------------------------------------*/
 
+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, 
+    size_t size, size_t *act_size, unsigned int flags);
+
+/*----------------------------------------------------------------------------*/
+
+static usbhid_iface_t usb_generic_iface = {
+	.get_event = usb_generic_hid_get_event,
+	.get_event_length = usb_generic_hid_get_event_length
+};
+
+static ddf_dev_ops_t usb_generic_hid_ops = {
+	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface
+};
+
+/*----------------------------------------------------------------------------*/
+
+static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
+{
+	if (fun == NULL || fun->driver_data) {
+		return 0;
+	}
+
+	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, 
+    size_t size, size_t *act_size, unsigned int flags)
+{
+	if (fun == NULL || fun->driver_data) {
+		return EINVAL;
+	}
+
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	if (hid_dev->input_report_size > size) {
+		return EINVAL;	// TODO: other error code
+	}
+	
+	/*! @todo This should probably be atomic. */
+	memcpy(buffer, hid_dev->input_report, hid_dev->input_report_size);
+	*act_size = hid_dev->input_report_size;
+	
+	// clear the buffer so that it will not be received twice
+	memset(hid_dev->input_report, 0, hid_dev->input_report_size);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)
+{	
+	/* Create the function exposed under /dev/devices. */
+	/** @todo Generate numbers for the devices? */
+	usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_GENERIC_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	fun->ops = &usb_generic_hid_ops;
+	fun->driver_data = hid_dev;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_generic_hid_init(usb_hid_dev_t *hid_dev)
+{
+	if (hid_dev == NULL) {
+		return EINVAL;
+	}
+	
+	return usb_generic_hid_create_function(hid_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+
 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, 
     uint8_t *buffer, size_t buffer_size)
Index: uspace/drv/usbhid/generic/hiddev.h
===================================================================
--- uspace/drv/usbhid/generic/hiddev.h	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/generic/hiddev.h	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -46,4 +46,8 @@
 const char *HID_GENERIC_CLASS_NAME;
 
+/*----------------------------------------------------------------------------*/
+
+int usb_generic_hid_init(struct usb_hid_dev *hid_dev);
+
 bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev,
     uint8_t *buffer, size_t buffer_size);
Index: uspace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/kbd/kbddev.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -766,4 +766,49 @@
 
 /*----------------------------------------------------------------------------*/
+
+static int usb_kbd_create_function(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL);
+	assert(hid_dev->usb_dev != NULL);
+	
+	/* Create the function exposed under /dev/devices. */
+	usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_KBD_FUN_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 = &hid_dev->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));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("Adding DDF function to class %s...\n", 
+	    HID_KBD_CLASS_NAME);
+	rc = ddf_fun_add_to_class(fun, HID_KBD_CLASS_NAME);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class %s: %s.\n",
+		    HID_KBD_CLASS_NAME, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
 /* API functions                                                              */
 /*----------------------------------------------------------------------------*/
@@ -930,4 +975,11 @@
 	usb_log_debug("HID/KBD device structure initialized.\n");
 	
+	usb_log_debug("Creating KBD function...\n");
+	int rc = usb_kbd_create_function(hid_dev);
+	if (rc != EOK) {
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
 	return EOK;
 }
Index: uspace/drv/usbhid/lgtch-ultrax/keymap.c
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/keymap.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/lgtch-ultrax/keymap.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -55,22 +55,22 @@
 	[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 */
+	[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 */
 };
 
Index: uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -58,4 +58,34 @@
 } 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;
+
 
 /*----------------------------------------------------------------------------*/
@@ -208,57 +238,6 @@
 /*----------------------------------------------------------------------------*/
 
-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;
-	
+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, 
@@ -269,7 +248,4 @@
 	}
 	
-	lgtch_dev->initialized = USB_LGTCH_STATUS_INITIALIZED;
-	usb_log_debug(NAME " HID/lgtch_ultrax device structure initialized.\n");
-	
 	/*
 	 * Store the initialized HID device and HID ops
@@ -279,15 +255,4 @@
 	fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
 	
-	/*
-	 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
-	 *    do nej.
-	 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 
-	 *    vyplnenu strukturu usbhid_iface_t.
-	 * 3) klientska aplikacia - musi si rucne vytvorit telefon
-	 *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 
-	 *    k tej fcii.
-	 *    pouzit usb/classes/hid/iface.h - prvy int je telefon
-	 */
-
 	int rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
@@ -296,5 +261,4 @@
 		// TODO: Can / should I destroy the DDF function?
 		ddf_fun_destroy(fun);
-		usb_lgtch_free(&lgtch_dev);
 		return rc;
 	}
@@ -307,4 +271,70 @@
 		// 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;
@@ -356,4 +386,11 @@
 	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);
 
@@ -383,9 +420,4 @@
 	usb_hid_report_path_free(path);
 	
-	if (rc != EOK) {
-		usb_log_warning(NAME "Error in usb_hid_boot_keyboard_input_report():"
-		    "%s\n", str_error(rc));
-	}
-	
 	return true;
 }
Index: uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -42,43 +42,4 @@
 
 /*----------------------------------------------------------------------------*/
-/**
- * USB/HID keyboard device type.
- *
- * Holds a reference to generic USB/HID device structure and keyboard-specific
- * data, such as currently pressed keys, modifiers and lock keys.
- *
- * Also holds a IPC phone to the console (since there is now no other way to 
- * communicate with it).
- *
- * @note Storing active lock keys in this structure results in their setting
- *       being device-specific.
- */
-typedef struct usb_lgtch_ultrax_t {
-	/** Previously pressed keys (not translated to key codes). */
-	int32_t *keys_old;
-	/** Currently pressed keys (not translated to key codes). */
-	int32_t *keys;
-	/** Count of stored keys (i.e. number of keys in the report). */
-	size_t key_count;
-	
-	/** IPC phone to the console device (for sending key events). */
-	int console_phone;
-
-	/** Information for auto-repeat of keys. */
-//	usb_kbd_repeat_t repeat;
-	
-	/** Mutex for accessing the information about auto-repeat. */
-//	fibril_mutex_t *repeat_mtx;
-
-	/** State of the structure (for checking before use). 
-	 * 
-	 * 0 - not initialized
-	 * 1 - initialized
-	 * -1 - ready for destroying
-	 */
-	int initialized;
-} usb_lgtch_ultrax_t;
-
-/*----------------------------------------------------------------------------*/
 
 int usb_lgtch_init(struct usb_hid_dev *hid_dev);
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/main.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -99,20 +99,4 @@
 	usb_log_debug("USB/HID device structure initialized.\n");
 	
-	/* Create the function exposed under /dev/devices. */
-	ddf_fun_t *hid_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 
-	    usb_hid_get_function_name(hid_dev));
-	if (hid_fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		usb_hid_free(&hid_dev);
-		return ENOMEM;
-	}
-	
-	/*
-	 * Store the initialized HID device and HID ops
-	 * to the DDF function.
-	 */
-	hid_fun->ops = &hid_dev->ops;
-	hid_fun->driver_data = hid_dev;   // TODO: maybe change to hid_dev->data
-	
 	/*
 	 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
@@ -125,25 +109,4 @@
 	 *    pouzit usb/classes/hid/iface.h - prvy int je telefon
 	 */
-
-	rc = ddf_fun_bind(hid_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(hid_fun);
-		usb_hid_free(&hid_dev);
-		return rc;
-	}
-	
-	rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev));
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class 'hid': %s.\n",
-		    str_error(rc));
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(hid_fun);
-		usb_hid_free(&hid_dev);
-		return rc;
-	}
 	
 	/* Start automated polling function.
Index: uspace/drv/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/mouse/mousedev.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -39,4 +39,5 @@
 #include <usb/classes/hid.h>
 #include <usb/classes/hidreq.h>
+#include <usb/classes/hidut.h>
 #include <errno.h>
 #include <str_error.h>
@@ -45,4 +46,6 @@
 #include "mousedev.h"
 #include "../usbhid.h"
+
+#define NAME "mouse"
 
 /*----------------------------------------------------------------------------*/
@@ -62,4 +65,5 @@
 /** Default idle rate for mouses. */
 static const uint8_t IDLE_RATE = 0;
+static const size_t USB_MOUSE_BUTTON_COUNT = 3;
 
 /*----------------------------------------------------------------------------*/
@@ -170,61 +174,168 @@
 /*----------------------------------------------------------------------------*/
 
-static bool usb_mouse_process_boot_report(usb_mouse_t *mouse_dev,
+static bool usb_mouse_process_boot_report(usb_hid_dev_t *hid_dev,
     uint8_t *buffer, size_t buffer_size)
 {
+	usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
+	
 	usb_log_debug2("got buffer: %s.\n",
 	    usb_debug_str_buffer(buffer, buffer_size, 0));
-
-	uint8_t butt = buffer[0];
-	char str_buttons[4] = {
-		butt & 1 ? '#' : '.',
-		butt & 2 ? '#' : '.',
-		butt & 4 ? '#' : '.',
-		0
-	};
-
-	int shift_x = ((int) buffer[1]) - 127;
-	int shift_y = ((int) buffer[2]) - 127;
-	int wheel = ((int) buffer[3]) - 127;
-
-	if (buffer[1] == 0) {
-		shift_x = 0;
-	}
-	if (buffer[2] == 0) {
-		shift_y = 0;
-	}
-	if (buffer[3] == 0) {
-		wheel = 0;
-	}
-	
-	if (mouse_dev->console_phone >= 0) {
-		usb_log_debug("Console phone: %d\n", mouse_dev->console_phone);
-		if ((shift_x != 0) || (shift_y != 0)) {
-			/* FIXME: guessed for QEMU */
+	
+	if (mouse_dev->console_phone < 0) {
+		usb_log_error(NAME " No console phone.\n");
+		return false;	// ??
+	}
+
+	/*
+	 * parse the input report
+	 */
+	
+	usb_log_debug(NAME " Calling usb_hid_parse_report() with "
+	    "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 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;
+	}
+	
+	/*
+	 * X
+	 */
+	int shift_x = 0;
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 
+	    USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
+
+	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_REPORT_TYPE_INPUT);
+
+	if (field != NULL) {
+		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
+		    field->usage);
+		shift_x = field->value;
+	}
+
+	usb_hid_report_path_free(path);
+	
+	/*
+	 * Y
+	 */
+	int shift_y = 0;
+	
+	path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP, 
+	    USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
+
+	usb_hid_report_path_set_report_id(path, report_id);
+
+	field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END, 
+	    USB_HID_REPORT_TYPE_INPUT);
+
+	if (field != NULL) {
+		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
+		    field->usage);
+		shift_y = field->value;
+	}
+
+	usb_hid_report_path_free(path);
+	
+	if ((shift_x != 0) || (shift_y != 0)) {
+		async_req_2_0(mouse_dev->console_phone,
+		    MEVENT_MOVE, shift_x, shift_y);
+	}
+	
+	/*
+	 * Buttons
+	 */
+	path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
+	usb_hid_report_path_set_report_id(path, report_id);
+	
+	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);
+
+	if (field != NULL) {
+		usb_log_debug(NAME " VALUE(%X) USAGE(%X)\n", field->value, 
+		    field->usage);
+		
+		if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
+		    && field->value != 0) {
 			async_req_2_0(mouse_dev->console_phone,
-			    MEVENT_MOVE,
-			    - shift_x / 10,  - shift_y / 10);
-		} else {
-			usb_log_error("No move reported\n");
-		}
-		if (butt) {
-			/* FIXME: proper button clicking. */
-			async_req_2_0(mouse_dev->console_phone,
-			    MEVENT_BUTTON, 1, 1);
-			async_req_2_0(mouse_dev->console_phone,
-			    MEVENT_BUTTON, 1, 0);
-		}
-	} else {
-		usb_log_error("No console phone in mouse!!\n");
-	}
-
-	usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
-	    str_buttons, shift_x, shift_y, wheel);
-
-	/* Guess. */
-	//async_usleep(1000);
-	// no sleep right now
+			    MEVENT_BUTTON, field->usage, 1);
+			mouse_dev->buttons[field->usage - field->usage_minimum]
+			    = field->value;
+		} else if (
+		    mouse_dev->buttons[field->usage - field->usage_minimum] != 0
+		    && field->value == 0) {
+		       async_req_2_0(mouse_dev->console_phone,
+			   MEVENT_BUTTON, field->usage, 0);
+		       mouse_dev->buttons[field->usage - field->usage_minimum]
+			   = field->value;
+	       }
+		
+		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;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_mouse_create_function(usb_hid_dev_t *hid_dev)
+{
+	/* Create the function exposed under /dev/devices. */
+	usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_MOUSE_FUN_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 = &hid_dev->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));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("Adding DDF function to class %s...\n", 
+	    HID_MOUSE_CLASS_NAME);
+	rc = ddf_fun_add_to_class(fun, HID_MOUSE_CLASS_NAME);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class %s: %s.\n",
+		    HID_MOUSE_CLASS_NAME, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	return EOK;
 }
 
@@ -248,4 +359,13 @@
 	}
 	
+	mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT, 
+	    sizeof(int32_t));
+	
+	if (mouse_dev->buttons == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(mouse_dev);
+		return ENOMEM;
+	}
+	
 	// save the Mouse device structure into the HID device structure
 	hid_dev->data = mouse_dev;
@@ -255,6 +375,12 @@
 	
 	// TODO: how to know if the device supports the request???
-	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
-	    hid_dev->usb_dev->interface_no, IDLE_RATE);
+//	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
+//	    hid_dev->usb_dev->interface_no, IDLE_RATE);
+	
+	int rc = usb_mouse_create_function(hid_dev);
+	if (rc != EOK) {
+		usb_mouse_free(&mouse_dev);
+		return rc;
+	}
 	
 	return EOK;
@@ -280,7 +406,6 @@
 		return false;
 	}
-	usb_mouse_t *mouse_dev = (usb_mouse_t *)hid_dev->data;
-	
-	return usb_mouse_process_boot_report(mouse_dev, buffer, buffer_size);
+	
+	return usb_mouse_process_boot_report(hid_dev, buffer, buffer_size);
 }
 
Index: uspace/drv/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.h	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/mouse/mousedev.h	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -49,4 +49,6 @@
 	/** IPC phone to console (consumer). */
 	int console_phone;
+	
+	int32_t *buttons;
 } usb_mouse_t;
 
Index: uspace/drv/usbhid/usbhid.c
===================================================================
--- uspace/drv/usbhid/usbhid.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/usbhid.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -136,5 +136,5 @@
 	
 	// set the init callback
-	hid_dev->subdrivers[0].init = NULL;
+	hid_dev->subdrivers[0].init = usb_generic_hid_init;
 	
 	// set the polling callback
@@ -490,4 +490,30 @@
 	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);
+			}
+		}
+	}
+	
+	/*! @todo This should probably be atomic. */
+	memcpy(hid_dev->input_report, buffer, buffer_size);
+	hid_dev->input_report_size = buffer_size;
+	
 	bool cont = false;
 	
@@ -528,36 +554,36 @@
 /*----------------------------------------------------------------------------*/
 
-const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
-{
-	switch (hid_dev->poll_pipe_index) {
-	case USB_HID_KBD_POLL_EP_NO:
-		return HID_KBD_FUN_NAME;
-		break;
-	case USB_HID_MOUSE_POLL_EP_NO:
-		return HID_MOUSE_FUN_NAME;
-		break;
-	default:
-		return HID_GENERIC_FUN_NAME;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
-{
-	// this means that only boot protocol keyboards will be connected
-	// to the console; there is probably no better way to do this
-	
-	switch (hid_dev->poll_pipe_index) {
-	case USB_HID_KBD_POLL_EP_NO:
-		return HID_KBD_CLASS_NAME;
-		break;
-	case USB_HID_MOUSE_POLL_EP_NO:
-		return HID_MOUSE_CLASS_NAME;
-		break;
-	default:
-		return HID_GENERIC_CLASS_NAME;
-	}
-}
+//const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
+//{
+//	switch (hid_dev->poll_pipe_index) {
+//	case USB_HID_KBD_POLL_EP_NO:
+//		return HID_KBD_FUN_NAME;
+//		break;
+//	case USB_HID_MOUSE_POLL_EP_NO:
+//		return HID_MOUSE_FUN_NAME;
+//		break;
+//	default:
+//		return HID_GENERIC_FUN_NAME;
+//	}
+//}
+
+/*----------------------------------------------------------------------------*/
+
+//const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
+//{
+//	// this means that only boot protocol keyboards will be connected
+//	// to the console; there is probably no better way to do this
+	
+//	switch (hid_dev->poll_pipe_index) {
+//	case USB_HID_KBD_POLL_EP_NO:
+//		return HID_KBD_CLASS_NAME;
+//		break;
+//	case USB_HID_MOUSE_POLL_EP_NO:
+//		return HID_MOUSE_CLASS_NAME;
+//		break;
+//	default:
+//		return HID_GENERIC_CLASS_NAME;
+//	}
+//}
 
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/usbhid/usbhid.h
===================================================================
--- uspace/drv/usbhid/usbhid.h	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhid/usbhid.h	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -93,4 +93,8 @@
 	usb_hid_report_t *report;
 	
+	uint8_t *input_report;
+	
+	size_t input_report_size;
+	
 	/** Arbitrary data (e.g. a special structure for handling keyboard). */
 	void *data;
@@ -120,7 +124,7 @@
      void *arg);
 
-const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
+//const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
 
-const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
+//const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
 
 void usb_hid_free(usb_hid_dev_t **hid_dev);
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/drv/usbhub/usbhub.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -411,5 +411,5 @@
 static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     usb_hub_status_t status) {
-	int opResult;
+	int opResult = EOK;
 	if (!usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) {
 		//restart power on hub
@@ -431,11 +431,14 @@
 			}
 		}
-		opResult = usb_hub_clear_feature(hub_info->control_pipe,
-		    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
+	}
+	if(opResult!=EOK){
+		return opResult;//no feature clearing
+	}
+	opResult = usb_hub_clear_feature(hub_info->control_pipe,
+	    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
 		if (opResult != EOK) {
-			usb_log_error("cannnot clear hub power change flag: "
-			    "%d\n",
-			    opResult);
-		}
+		usb_log_error("cannnot clear hub power change flag: "
+		    "%d\n",
+		    opResult);
 	}
 	return opResult;
Index: uspace/lib/drv/include/usbhid_iface.h
===================================================================
--- uspace/lib/drv/include/usbhid_iface.h	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/lib/drv/include/usbhid_iface.h	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -72,24 +72,21 @@
 /** USB HID device communication interface. */
 typedef struct {
-	/** Get number of items in the event.
+	/** Get size of the event in bytes.
 	 *
 	 * @param[in] fun DDF function answering the request.
 	 * @return Number of events or error code.
 	 */
-	int (*get_event_length)(ddf_fun_t *fun);
+	size_t (*get_event_length)(ddf_fun_t *fun);
 
 	/** Get single event from the HID device.
 	 *
 	 * @param[in] fun DDF function answering the request.
-	 * @param[out] usage_page Array of usage pages and usages.
-	 * @param[out] usage Array of data (1:1 with @p usage).
-	 * @param[in] size Size of @p usage and @p data arrays.
+	 * @param[out] buffer Buffer with raw data from the device.
 	 * @param[out] act_size Actual number of returned events.
 	 * @param[in] flags Flags (see USBHID_IFACE_FLAG_*).
 	 * @return Error code.
 	 */
-	int (*get_event)(ddf_fun_t *fun,
-	    uint16_t *usage_page, uint16_t *usage, size_t size, size_t *act_size,
-	    unsigned int flags);
+	int (*get_event)(ddf_fun_t *fun, int32_t *buffer, size_t size,
+	    size_t *act_size, unsigned int flags);
 } usbhid_iface_t;
 
Index: uspace/lib/usb/include/usb/classes/hidut.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidut.h	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/lib/usb/include/usb/classes/hidut.h	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -59,5 +59,8 @@
 	USB_HIDUT_USAGE_GENERIC_DESKTOP_GAMEPAD = 5,
 	USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD = 6,
-	USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_X = 0x30,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_Y = 0x31,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL = 0x38
 	/* USB_HIDUT_USAGE_GENERIC_DESKTOP_ = , */
 	
Index: uspace/lib/usb/src/hiddescriptor.c
===================================================================
--- uspace/lib/usb/src/hiddescriptor.c	(revision b9d7965c030b36edbe57f98e48b3ec70bdefd5ea)
+++ uspace/lib/usb/src/hiddescriptor.c	(revision acdbd7809611d464f303fead160becfa3666d8be)
@@ -640,5 +640,5 @@
 
 		usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
-		usb_log_debug("\t\tSIZE: %X\n", report_item->size);				
+		usb_log_debug("\t\tSIZE: %zu\n", report_item->size);
 		usb_log_debug("\t\tLOGMIN: %d\n", report_item->logical_minimum);
 		usb_log_debug("\t\tLOGMAX: %d\n", report_item->logical_maximum);		
@@ -679,6 +679,6 @@
 		usb_log_debug("Report ID: %d\n", report_des->report_id);
 		usb_log_debug("\tType: %d\n", report_des->type);
-		usb_log_debug("\tLength: %d\n", report_des->bit_length);		
-		usb_log_debug("\tItems: %d\n", report_des->item_length);		
+		usb_log_debug("\tLength: %zu\n", report_des->bit_length);
+		usb_log_debug("\tItems: %zu\n", report_des->item_length);
 
 		usb_hid_descriptor_print_list(&report_des->report_items);
