Index: uspace/app/bdsh/cmds/modules/mount/mount.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mount/mount.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/app/bdsh/cmds/modules/mount/mount.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -27,4 +27,5 @@
  */
 
+#include <loc.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -67,7 +68,9 @@
 {
 	LIST_INITIALIZE(mtab_list);
+	mtab_ent_t *old_ent = NULL;
+	char *svc_name;
+	int rc;
+
 	get_mtab_list(&mtab_list);
-
-	mtab_ent_t *old_ent = NULL;
 
 	list_foreach(mtab_list, cur) {
@@ -83,10 +86,19 @@
 		if (mtab_ent->instance)
 			printf("/%d", mtab_ent->instance);
-		printf(" on %s ", mtab_ent->mp);
+
+		printf(" %s", mtab_ent->mp);
+
+		rc = loc_service_get_name(mtab_ent->service_id, &svc_name);
+		if (rc == EOK) {
+			printf(" %s", svc_name);
+			free(svc_name);
+		} else {
+			printf(" (%" PRIun ")", mtab_ent->service_id);
+		}
 
 		if (str_size(mtab_ent->opts) > 0)
-			printf("opts=%s ", mtab_ent->opts);
+			printf(" (%s)", mtab_ent->opts);
 
-		printf("(service=%" PRIun ")\n", mtab_ent->service_id);
+		putchar('\n');
 	}
 
Index: uspace/app/locinfo/locinfo.c
===================================================================
--- uspace/app/locinfo/locinfo.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/app/locinfo/locinfo.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -89,4 +89,5 @@
 			}
 			printf("\t%s (%" PRIun ")\n", svc_name, svc_ids[j]);
+			free(svc_name);
 		}
 
Index: uspace/drv/bus/usb/ehci/hc_iface.c
===================================================================
--- uspace/drv/bus/usb/ehci/hc_iface.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/ehci/hc_iface.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -56,6 +56,6 @@
  * @return Error code.
  */
-static int request_address(ddf_fun_t *fun, usb_speed_t speed,
-    usb_address_t *address)
+static int request_address(ddf_fun_t *fun, usb_address_t *address, bool strict,
+    usb_speed_t speed)
 {
 	UNSUPPORTED("request_address");
@@ -120,5 +120,5 @@
  */
 static int register_endpoint(ddf_fun_t *fun,
-    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
+    usb_address_t address, usb_endpoint_t endpoint,
     usb_transfer_type_t transfer_type, usb_direction_t direction,
     size_t max_packet_size, unsigned int interval)
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -127,15 +127,16 @@
 	assert(hub_fun);
 
-	const usb_address_t hub_address =
-	    usb_device_manager_get_free_address(
-	        &instance->generic.dev_manager, USB_SPEED_FULL);
-	if (hub_address <= 0) {
+	/* Try to get address 1 for root hub. */
+	instance->rh.address = 1;
+	int ret = usb_device_manager_request_address(
+	    &instance->generic.dev_manager, &instance->rh.address, false,
+	    USB_SPEED_FULL);
+	if (ret != EOK) {
 		usb_log_error("Failed to get OHCI root hub address: %s\n",
-		    str_error(hub_address));
-		return hub_address;
-	}
-	instance->rh.address = hub_address;
-	usb_device_manager_bind(
-	    &instance->generic.dev_manager, hub_address, hub_fun->handle);
+		    str_error(ret));
+		return ret;
+	}
+	usb_device_manager_bind_address(&instance->generic.dev_manager,
+	    instance->rh.address, hub_fun->handle);
 
 #define CHECK_RET_UNREG_RETURN(ret, message...) \
@@ -143,13 +144,14 @@
 	usb_log_error(message); \
 	usb_endpoint_manager_remove_ep( \
-	    &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, \
-	    NULL, NULL);\
-	usb_device_manager_release( \
-	    &instance->generic.dev_manager, hub_address); \
+	    &instance->generic.ep_manager, instance->rh.address, 0, \
+	    USB_DIRECTION_BOTH, NULL, NULL); \
+	usb_device_manager_release_address( \
+	    &instance->generic.dev_manager, instance->rh.address); \
 	return ret; \
 } else (void)0
-	int ret = usb_endpoint_manager_add_ep(
-	    &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH,
-	    USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0, NULL, NULL);
+	ret = usb_endpoint_manager_add_ep(
+	    &instance->generic.ep_manager, instance->rh.address, 0,
+	    USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64,
+	    0, NULL, NULL);
 	CHECK_RET_UNREG_RETURN(ret,
 	    "Failed to register root hub control endpoint: %s.\n",
@@ -193,6 +195,6 @@
 	list_initialize(&instance->pending_batches);
 
-	hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
-	    bandwidth_count_usb11);
+	hcd_init(&instance->generic, USB_SPEED_FULL,
+	    BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
 	instance->generic.private_data = instance;
 	instance->generic.schedule = hc_schedule;
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -76,25 +76,16 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Get address of the device identified by handle.
- *
- * @param[in] dev DDF instance of the device to use.
- * @param[in] iid (Unused).
- * @param[in] call Pointer to the call that represents interrupt.
- */
-static int usb_iface_get_address(
-    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
+/** Get USB address assigned to root hub.
+ *
+ * @param[in] fun Root hub function.
+ * @param[out] address Store the address here.
+ * @return Error code.
+ */
+static int rh_get_my_address(ddf_fun_t *fun, usb_address_t *address)
 {
 	assert(fun);
-	usb_device_manager_t *manager =
-	    &dev_to_ohci(fun->dev)->hc.generic.dev_manager;
-
-	const usb_address_t addr =
-	    usb_device_manager_find_address(manager, handle);
-	if (addr < 0) {
-		return addr;
-	}
 
 	if (address != NULL) {
-		*address = addr;
+		*address = dev_to_ohci(fun->dev)->hc.rh.address;
 	}
 
@@ -108,5 +99,5 @@
  * @return Error code.
  */
-static int usb_iface_get_hc_handle(
+static int rh_get_hc_handle(
     ddf_fun_t *fun, devman_handle_t *handle)
 {
@@ -122,6 +113,6 @@
 /** Root hub USB interface */
 static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle,
-	.get_address = usb_iface_get_address
+	.get_hc_handle = rh_get_hc_handle,
+	.get_my_address = rh_get_my_address,
 };
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -199,6 +199,6 @@
 #undef CHECK_RET_RETURN
 
-	hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
-	    bandwidth_count_usb11);
+	hcd_init(&instance->generic, USB_SPEED_FULL,
+	    BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);
 
 	instance->generic.private_data = instance;
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -89,30 +89,4 @@
 };
 /*----------------------------------------------------------------------------*/
-/** Get address of the device identified by handle.
- *
- * @param[in] fun DDF instance of the function to use.
- * @param[in] handle DDF handle of the driver seeking its USB address.
- * @param[out] address Found address.
- */
-static int usb_iface_get_address(
-    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
-{
-	assert(fun);
-	usb_device_manager_t *manager =
-	    &dev_to_uhci(fun->dev)->hc.generic.dev_manager;
-	const usb_address_t addr =
-	    usb_device_manager_find_address(manager, handle);
-
-	if (addr < 0) {
-		return addr;
-	}
-
-	if (address != NULL) {
-		*address = addr;
-	}
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
 /** Gets handle of the respective hc.
  *
@@ -135,5 +109,4 @@
 static usb_iface_t usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle,
-	.get_address = usb_iface_get_address
 };
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/bus/usb/usbflbk/main.c
===================================================================
--- uspace/drv/bus/usb/usbflbk/main.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbflbk/main.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -74,14 +74,4 @@
 }
 
-/** Callback when new device is about to be removed.
- *
- * @param dev Representation of a generic DDF device.
- * @return Error code.
- */
-static int usbfallback_device_remove(usb_device_t *dev)
-{
-	return EOK;
-}
-
 /** Callback when new device is removed and recognized as gone by DDF.
  *
@@ -107,5 +97,5 @@
 static const usb_driver_ops_t usbfallback_driver_ops = {
 	.device_add = usbfallback_device_add,
-	.device_rem = usbfallback_device_remove,
+	.device_rem = usbfallback_device_gone,
 	.device_gone = usbfallback_device_gone,
 };
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -61,19 +61,12 @@
 
 /*----------------------------------------------------------------------------*/
-
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
-
-static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
+static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
     size_t size, size_t *act_size, int *event_nr, unsigned int flags);
-
 static int usb_generic_hid_client_connected(ddf_fun_t *fun);
-
 static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun);
-
-static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
+static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
     size_t size, size_t *actual_size);
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static usbhid_iface_t usb_generic_iface = {
 	.get_event = usb_generic_hid_get_event,
@@ -82,12 +75,10 @@
 	.get_report_descriptor = usb_generic_get_report_descriptor
 };
-
+/*----------------------------------------------------------------------------*/
 static ddf_dev_ops_t usb_generic_hid_ops = {
 	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
 	.open = usb_generic_hid_client_connected
 };
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
 {
@@ -99,5 +90,5 @@
 	}
 
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	const usb_hid_dev_t *hid_dev = fun->driver_data;
 
 	usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
@@ -106,8 +97,6 @@
 	return hid_dev->max_input_report_size;
 }
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
+/*----------------------------------------------------------------------------*/
+static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer,
     size_t size, size_t *act_size, int *event_nr, unsigned int flags)
 {
@@ -120,8 +109,8 @@
 	}
 
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	const usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
 
 	if (hid_dev->input_report_size > size) {
-		usb_log_debug("input_report_size > size (%zu, %zu)\n", 
+		usb_log_debug("input_report_size > size (%zu, %zu)\n",
 		    hid_dev->input_report_size, size);
 		return EINVAL;	// TODO: other error code
@@ -129,5 +118,5 @@
 
 	/*! @todo This should probably be somehow atomic. */
-	memcpy(buffer, hid_dev->input_report, 
+	memcpy(buffer, hid_dev->input_report,
 	    hid_dev->input_report_size);
 	*act_size = hid_dev->input_report_size;
@@ -138,7 +127,5 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
 {
@@ -150,15 +137,13 @@
 	}
 
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
-
-	usb_log_debug2("hid_dev->report_desc_size = %zu\n", 
+	const usb_hid_dev_t *hid_dev = fun->driver_data;
+
+	usb_log_debug2("hid_dev->report_desc_size = %zu\n",
 	    hid_dev->report_desc_size);
 
 	return hid_dev->report_desc_size;
 }
-
-/*----------------------------------------------------------------------------*/
-
-static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
+/*----------------------------------------------------------------------------*/
+static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc,
     size_t size, size_t *actual_size)
 {
@@ -170,5 +155,5 @@
 	}
 
-	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	const usb_hid_dev_t *hid_dev = fun->driver_data;
 
 	if (hid_dev->report_desc_size > size) {
@@ -181,7 +166,5 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static int usb_generic_hid_client_connected(ddf_fun_t *fun)
 {
@@ -189,12 +172,12 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 void usb_generic_hid_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
 	ddf_fun_t *fun = data;
-	const int ret = ddf_fun_unbind(fun);
-	if (ret != EOK) {
+	if (fun == NULL)
+		return;
+
+	if (ddf_fun_unbind(fun) != EOK) {
 		usb_log_error("Failed to unbind generic hid fun.\n");
 		return;
@@ -206,7 +189,5 @@
 	ddf_fun_destroy(fun);
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
 {
@@ -216,5 +197,4 @@
 
 	/* Create the exposed function. */
-	/** @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, 
@@ -225,4 +205,7 @@
 	}
 
+	/* This is nasty, both device and this function have the same
+	 * driver data, thus destruction causes to double free */
+	fun->driver_data = hid_dev;
 	fun->ops = &usb_generic_hid_ops;
 
@@ -231,10 +214,8 @@
 		usb_log_error("Could not bind DDF function: %s.\n",
 		    str_error(rc));
+		fun->driver_data = NULL;
 		ddf_fun_destroy(fun);
 		return rc;
 	}
-	/* This is nasty both device and this function have the same
-	 * driver data, thus destruction would lead to double free */
-	fun->driver_data = hid_dev;
 
 	usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
@@ -243,12 +224,9 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
 	return true;
 }
-
 /**
  * @}
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -41,4 +41,5 @@
 #include <io/keycode.h>
 #include <io/console.h>
+#include <abi/ipc/methods.h>
 #include <ipc/kbdev.h>
 #include <async.h>
@@ -86,5 +87,4 @@
 
 /*----------------------------------------------------------------------------*/
-
 /** Keyboard polling endpoint description for boot protocol class. */
 const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
@@ -101,50 +101,40 @@
 
 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
-
-/*----------------------------------------------------------------------------*/
-
-enum {
-	USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
+/*----------------------------------------------------------------------------*/
+static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[] = {
+	0x05, 0x01,  /* Usage Page (Generic Desktop), */
+	0x09, 0x06,  /* Usage (Keyboard), */
+	0xA1, 0x01,  /* Collection (Application), */
+	0x75, 0x01,  /*   Report Size (1), */
+	0x95, 0x08,  /*   Report Count (8), */
+	0x05, 0x07,  /*   Usage Page (Key Codes); */
+	0x19, 0xE0,  /*   Usage Minimum (224), */
+	0x29, 0xE7,  /*   Usage Maximum (231), */
+	0x15, 0x00,  /*   Logical Minimum (0), */
+	0x25, 0x01,  /*   Logical Maximum (1), */
+	0x81, 0x02,  /*   Input (Data, Variable, Absolute),  ; Modifier byte */
+	0x95, 0x01,  /*   Report Count (1), */
+	0x75, 0x08,  /*   Report Size (8), */
+	0x81, 0x01,  /*   Input (Constant),                  ; Reserved byte */
+	0x95, 0x05,  /*   Report Count (5), */
+	0x75, 0x01,  /*   Report Size (1), */
+	0x05, 0x08,  /*   Usage Page (Page# for LEDs), */
+	0x19, 0x01,  /*   Usage Minimum (1), */
+	0x29, 0x05,  /*   Usage Maxmimum (5), */
+	0x91, 0x02,  /*   Output (Data, Variable, Absolute),  ; LED report */
+	0x95, 0x01,  /*   Report Count (1), */
+	0x75, 0x03,  /*   Report Size (3), */
+	0x91, 0x01,  /*   Output (Constant),            ; LED report padding */
+	0x95, 0x06,  /*   Report Count (6), */
+	0x75, 0x08,  /*   Report Size (8), */
+	0x15, 0x00,  /*   Logical Minimum (0), */
+	0x25, 0xff,  /*   Logical Maximum (255), */
+	0x05, 0x07,  /*   Usage Page (Key Codes), */
+	0x19, 0x00,  /*   Usage Minimum (0), */
+	0x29, 0xff,  /*   Usage Maximum (255), */
+	0x81, 0x00,  /*   Input (Data, Array),   ; Key arrays (6 bytes) */
+	0xC0         /* End Collection */
 };
-
-static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
-    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
-        0x05, 0x01,  // Usage Page (Generic Desktop),
-        0x09, 0x06,  // Usage (Keyboard),
-        0xA1, 0x01,  // Collection (Application),
-        0x75, 0x01,  //   Report Size (1),
-        0x95, 0x08,  //   Report Count (8),       
-        0x05, 0x07,  //   Usage Page (Key Codes);
-        0x19, 0xE0,  //   Usage Minimum (224),
-        0x29, 0xE7,  //   Usage Maximum (231),
-        0x15, 0x00,  //   Logical Minimum (0),
-        0x25, 0x01,  //   Logical Maximum (1),
-        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
-	0x95, 0x01,  //   Report Count (1),
-        0x75, 0x08,  //   Report Size (8),
-        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
-        0x95, 0x05,  //   Report Count (5),
-        0x75, 0x01,  //   Report Size (1),
-        0x05, 0x08,  //   Usage Page (Page# for LEDs),
-        0x19, 0x01,  //   Usage Minimum (1),
-        0x29, 0x05,  //   Usage Maxmimum (5),
-        0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
-        0x95, 0x01,  //   Report Count (1),
-        0x75, 0x03,  //   Report Size (3),
-        0x91, 0x01,  //   Output (Constant),              ; LED report padding
-        0x95, 0x06,  //   Report Count (6),
-        0x75, 0x08,  //   Report Size (8),
-        0x15, 0x00,  //   Logical Minimum (0),
-        0x25, 0xff,  //   Logical Maximum (255),
-        0x05, 0x07,  //   Usage Page (Key Codes),
-        0x19, 0x00,  //   Usage Minimum (0),
-        0x29, 0xff,  //   Usage Maximum (255),
-        0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
-        0xC0           // End Collection
-
-};
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 typedef enum usb_kbd_flags {
 	USB_KBD_STATUS_UNINITIALIZED = 0,
@@ -152,17 +142,14 @@
 	USB_KBD_STATUS_TO_DESTROY = -1
 } usb_kbd_flags;
-
 /*----------------------------------------------------------------------------*/
 /* IPC method handler                                                         */
 /*----------------------------------------------------------------------------*/
-
-static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_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 session to it for
- * later use by the driver to notify about key events.
+ * Currently recognizes only two methods (IPC_M_CONNECT_TO_ME and KBDEV_SET_IND)
+ * IPC_M_CONNECT_TO_ME assumes the caller is the console and  stores IPC
+ * session to it for later use by the driver to notify about key events.
+ * KBDEV_SET_IND sets LED keyboard indicators.
  *
  * @param fun Device function handling the call.
@@ -173,41 +160,50 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	sysarg_t method = IPC_GET_IMETHOD(*icall);
-
-	usb_kbd_t *kbd_dev = (usb_kbd_t *) fun->driver_data;
-	if (kbd_dev == NULL) {
-		usb_log_debug("default_connection_handler: "
-		    "Missing parameter.\n");
+	if (fun == NULL || fun->driver_data == NULL) {
+		usb_log_error("%s: Missing parameter.\n", __FUNCTION__);
 		async_answer_0(icallid, EINVAL);
 		return;
 	}
 
-	async_sess_t *sess =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
-	if (sess != NULL) {
+	const sysarg_t method = IPC_GET_IMETHOD(*icall);
+	usb_kbd_t *kbd_dev = fun->driver_data;
+
+	switch (method) {
+	case KBDEV_SET_IND:
+		kbd_dev->mods = IPC_GET_ARG1(*icall);
+		usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
+		async_answer_0(icallid, EOK);
+		break;
+	/* This might be ugly but async_callback_receive_start makes no
+	 * difference for incorrect call and malloc failure. */
+	case IPC_M_CONNECT_TO_ME: {
+		async_sess_t *sess =
+		    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
+		/* Probably ENOMEM error, try again. */
+		if (sess == NULL) {
+			usb_log_warning(
+			    "Failed to create start console session.\n");
+			async_answer_0(icallid, EAGAIN);
+			break;
+		}
 		if (kbd_dev->console_sess == NULL) {
 			kbd_dev->console_sess = sess;
-			usb_log_debug("default_connection_handler: OK\n");
+			usb_log_debug("%s: OK\n", __FUNCTION__);
 			async_answer_0(icallid, EOK);
 		} else {
-			usb_log_debug("default_connection_handler: "
-			    "console session already set\n");
+			usb_log_error("%s: console session already set\n",
+			   __FUNCTION__);
 			async_answer_0(icallid, ELIMIT);
 		}
-	} else {
-		switch (method) {
-		case KBDEV_SET_IND:
-			kbd_dev->mods = IPC_GET_ARG1(*icall);
-			usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
-			async_answer_0(icallid, EOK);
-			break;
-		default:
-			usb_log_debug("default_connection_handler: Wrong function.\n");
+		break;
+	}
+	default:
+			usb_log_error("%s: Unknown method: %d.\n",
+			    __FUNCTION__, (int) method);
 			async_answer_0(icallid, EINVAL);
 			break;
-		}
-	}
-}
-
+	}
+
+}
 /*----------------------------------------------------------------------------*/
 /* Key processing functions                                                   */
@@ -226,5 +222,5 @@
  * @param kbd_dev Keyboard device structure.
  */
-static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
+static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
 {
 	if (kbd_dev->output_size == 0) {
@@ -274,13 +270,15 @@
 	}
 
-	usb_log_debug("Output report buffer: %s\n", 
-	    usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
+	usb_log_debug("Output report buffer: %s\n",
+	    usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
 	        0));
 
-	usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe, 
-	    hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
+	rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
+	    hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
 	    kbd_dev->output_buffer, kbd_dev->output_size);
-}
-
+	if (rc != EOK) {
+		usb_log_warning("Failed to set kbd indicators.\n");
+	}
+}
 /*----------------------------------------------------------------------------*/
 /** Send key event.
@@ -291,6 +289,5 @@
  * @param key Key code
  */
-void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type, 
-    unsigned int key)
+void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key)
 {
 	usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
@@ -302,11 +299,13 @@
 
 	async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
-	async_msg_2(exch, KBDEV_EVENT, type, key);
-	async_exchange_end(exch);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static inline int usb_kbd_is_lock(unsigned int key_code) 
+	if (exch != NULL) {
+		async_msg_2(exch, KBDEV_EVENT, type, key);
+		async_exchange_end(exch);
+	} else {
+		usb_log_warning("Failed to send key to console.\n");
+	}
+}
+/*----------------------------------------------------------------------------*/
+static inline int usb_kbd_is_lock(unsigned int key_code)
 {
 	return (key_code == KC_NUM_LOCK
@@ -314,5 +313,5 @@
 	    || key_code == KC_CAPS_LOCK);
 }
-
+/*----------------------------------------------------------------------------*/
 static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
 {
@@ -325,5 +324,4 @@
 	return (size_t) -1;
 }
-
 /*----------------------------------------------------------------------------*/
 /**
@@ -342,9 +340,7 @@
  * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
  */
-static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
+static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev,
     usb_kbd_t *kbd_dev)
 {
-	unsigned int key;
-	size_t i;
 
 	/*
@@ -356,8 +352,8 @@
 	 * whole input report.
 	 */
-	i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
+	size_t i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
 	    kbd_dev->key_count);
 	if (i != (size_t) -1) {
-		usb_log_debug("Detected phantom state.\n");
+		usb_log_error("Detected phantom state.\n");
 		return;
 	}
@@ -367,15 +363,15 @@
 	 */
 	for (i = 0; i < kbd_dev->key_count; i++) {
-		int32_t old_key = kbd_dev->keys_old[i];
+		const int32_t old_key = kbd_dev->keys_old[i];
 		/* Find the old key among currently pressed keys. */
-		size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
+		const size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
 		    kbd_dev->key_count);
 		/* If the key was not found, we need to signal release. */
 		if (pos == (size_t) -1) {
-			key = usbhid_parse_scancode(old_key);
+			const unsigned key = usbhid_parse_scancode(old_key);
 			if (!usb_kbd_is_lock(key)) {
 				usb_kbd_repeat_stop(kbd_dev, key);
 			}
-			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
+			usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
 			usb_log_debug2("Key released: %u "
 			    "(USB code %" PRIu32 ")\n", key, old_key);
@@ -387,15 +383,15 @@
 	 */
 	for (i = 0; i < kbd_dev->key_count; ++i) {
-		int32_t new_key = kbd_dev->keys[i];
+		const int32_t new_key = kbd_dev->keys[i];
 		/* Find the new key among already pressed keys. */
-		size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
-		    kbd_dev->key_count);
+		const size_t pos = find_in_array_int32(new_key,
+		    kbd_dev->keys_old, kbd_dev->key_count);
 		/* If the key was not found, we need to signal press. */
 		if (pos == (size_t) -1) {
-			key = usbhid_parse_scancode(kbd_dev->keys[i]);
+			unsigned key = usbhid_parse_scancode(kbd_dev->keys[i]);
 			if (!usb_kbd_is_lock(key)) {
 				usb_kbd_repeat_start(kbd_dev, key);
 			}
-			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
+			usb_kbd_push_ev(kbd_dev, KEY_PRESS, key);
 			usb_log_debug2("Key pressed: %u "
 			    "(USB code %" PRIu32 ")\n", key, new_key);
@@ -405,4 +401,5 @@
 	memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
 
+	// TODO Get rid of this
 	char key_buffer[512];
 	ddf_dump_buffer(key_buffer, 512,
@@ -410,5 +407,4 @@
 	usb_log_debug2("Stored keys %s.\n", key_buffer);
 }
-
 /*----------------------------------------------------------------------------*/
 /* General kbd functions                                                      */
@@ -436,10 +432,19 @@
 
 	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
-
-	usb_hid_report_path_set_report_id (path, hid_dev->report_id);
-
-	// fill in the currently pressed keys
-
+	if (path == NULL) {
+		usb_log_error("Failed to create hid/kbd report path.\n");
+		return;
+	}
+
+	int ret =
+	   usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+	if (ret != EOK) {
+		usb_log_error("Failed to append to hid/kbd report path.\n");
+		return;
+	}
+
+	usb_hid_report_path_set_report_id(path, hid_dev->report_id);
+
+	/* Fill in the currently pressed keys. */
 	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
 	    &hid_dev->report, NULL, path,
@@ -449,10 +454,10 @@
 
 	while (field != NULL) {
-		usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
+		usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
 		    field, field->value, field->usage);
-		
+
 		assert(i < kbd_dev->key_count);
 
-		// save the key usage
+		/* Save the key usage. */
 		if (field->value != 0) {
 			kbd_dev->keys[i] = field->usage;
@@ -474,43 +479,7 @@
 	usb_kbd_check_key_changes(hid_dev, kbd_dev);
 }
-
 /*----------------------------------------------------------------------------*/
 /* HID/KBD structure manipulation                                             */
 /*----------------------------------------------------------------------------*/
-
-static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
-{
-	kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * Creates a new USB/HID keyboard structure.
- *
- * The structure returned by this function is not initialized. Use 
- * usb_kbd_init() to initialize it prior to polling.
- *
- * @return New uninitialized structure for representing a USB/HID keyboard or
- *         NULL if not successful (memory error).
- */
-static usb_kbd_t *usb_kbd_new(void)
-{
-	usb_kbd_t *kbd_dev = 
-	    (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
-
-	if (kbd_dev == NULL) {
-		usb_log_error("No memory!\n");
-		return NULL;
-	}
-
-	kbd_dev->console_sess = NULL;
-	kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
-
-	return kbd_dev;
-}
-
-/*----------------------------------------------------------------------------*/
-
 static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
 {
@@ -528,8 +497,6 @@
 	}
 
-	/*
-	 * Store the initialized HID device and HID ops
-	 * to the DDF function.
-	 */
+	/* Store the initialized HID device and HID ops
+	 * to the DDF function. */
 	fun->ops = &kbd_dev->ops;
 	fun->driver_data = kbd_dev;
@@ -539,5 +506,5 @@
 		usb_log_error("Could not bind DDF function: %s.\n",
 		    str_error(rc));
-		fun->driver_data = NULL; /* We need this later */
+		fun->driver_data = NULL; /* We did not allocate this. */
 		ddf_fun_destroy(fun);
 		return rc;
@@ -547,5 +514,5 @@
 	    HID_KBD_FUN_NAME, fun->handle);
 
-	usb_log_debug("Adding DDF function to category %s...\n", 
+	usb_log_debug("Adding DDF function to category %s...\n",
 	    HID_KBD_CLASS_NAME);
 	rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
@@ -554,6 +521,12 @@
 		    "Could not add DDF function to category %s: %s.\n",
 		    HID_KBD_CLASS_NAME, str_error(rc));
-		fun->driver_data = NULL; /* We need this later */
-		ddf_fun_destroy(fun);
+		if (ddf_fun_unbind(fun) == EOK) {
+			fun->driver_data = NULL; /* We did not allocate this. */
+			ddf_fun_destroy(fun);
+		} else {
+			usb_log_error(
+			    "Failed to unbind `%s', will not destroy.\n",
+			    fun->name);
+		}
 		return rc;
 	}
@@ -562,5 +535,4 @@
 	return EOK;
 }
-
 /*----------------------------------------------------------------------------*/
 /* API functions                                                              */
@@ -591,29 +563,52 @@
 
 	if (hid_dev == NULL) {
-		usb_log_error("Failed to init keyboard structure: no structure"
-		    " given.\n");
+		usb_log_error(
+		    "Failed to init keyboard structure: no structure given.\n");
 		return EINVAL;
 	}
 
-	usb_kbd_t *kbd_dev = usb_kbd_new();
+	usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t));
 	if (kbd_dev == NULL) {
-		usb_log_error("Error while creating USB/HID KBD device "
-		    "structure.\n");
-		return ENOMEM;  // TODO: some other code??
-	}
+		usb_log_error("Failed to allocate KBD device structure.\n");
+		return ENOMEM;
+	}
+	/* Default values */
+	fibril_mutex_initialize(&kbd_dev->repeat_mtx);
+	kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
+	kbd_dev->ops.default_handler = default_connection_handler;
 
 	/* Store link to HID device */
 	kbd_dev->hid_dev = hid_dev;
 
-	/*
-	 * TODO: make more general
-	 */
+	/* Modifiers and locks */
+	kbd_dev->mods = DEFAULT_ACTIVE_MODS;
+
+	/* Autorepeat */
+	kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
+	kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
+
+
+	// TODO: make more general
 	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+	if (path == NULL) {
+		usb_log_error("Failed to create kbd report path.\n");
+		usb_kbd_destroy(kbd_dev);
+		return ENOMEM;
+	}
+
+	int ret =
+	    usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+	if (ret != EOK) {
+		usb_log_error("Failed to append item to kbd report path.\n");
+		usb_hid_report_path_free(path);
+		usb_kbd_destroy(kbd_dev);
+		return ret;
+	}
 
 	usb_hid_report_path_set_report_id(path, 0);
 
-	kbd_dev->key_count = usb_hid_report_size(
-	    &hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
+	kbd_dev->key_count =
+	    usb_hid_report_size(&hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
+
 	usb_hid_report_path_free(path);
 
@@ -621,30 +616,24 @@
 
 	kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
-
 	if (kbd_dev->keys == NULL) {
-		usb_log_error("No memory!\n");
-		free(kbd_dev);
+		usb_log_error("Failed to allocate key buffer.\n");
+		usb_kbd_destroy(kbd_dev);
 		return ENOMEM;
 	}
 
-	kbd_dev->keys_old = 
-		(int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
-
+	kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t));
 	if (kbd_dev->keys_old == NULL) {
-		usb_log_error("No memory!\n");
-		free(kbd_dev->keys);
-		free(kbd_dev);
+		usb_log_error("Failed to allocate old_key buffer.\n");
+		usb_kbd_destroy(kbd_dev);
 		return ENOMEM;
 	}
 
-	/*
-	 * Output report
-	 */
+	/* Output report */
 	kbd_dev->output_size = 0;
 	kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
 	    &kbd_dev->output_size, 0);
 	if (kbd_dev->output_buffer == NULL) {
-		usb_log_warning("Error creating output report buffer.\n");
-		free(kbd_dev->keys);
+		usb_log_error("Error creating output report buffer.\n");
+		usb_kbd_destroy(kbd_dev);
 		return ENOMEM;
 	}
@@ -653,92 +642,71 @@
 
 	kbd_dev->led_path = usb_hid_report_path();
-	usb_hid_report_path_append_item(
+	if (kbd_dev->led_path == NULL) {
+		usb_log_error("Failed to create kbd led report path.\n");
+		usb_kbd_destroy(kbd_dev);
+		return ENOMEM;
+	}
+
+	ret = usb_hid_report_path_append_item(
 	    kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
+	if (ret != EOK) {
+		usb_log_error("Failed to append to kbd/led report path.\n");
+		usb_kbd_destroy(kbd_dev);
+		return ret;
+	}
 
 	kbd_dev->led_output_size = usb_hid_report_size(
 	    &hid_dev->report, 0, USB_HID_REPORT_TYPE_OUTPUT);
 
-	usb_log_debug("Output report size (in items): %zu\n", 
+	usb_log_debug("Output report size (in items): %zu\n",
 	    kbd_dev->led_output_size);
 
-	kbd_dev->led_data = (int32_t *)calloc(
-	    kbd_dev->led_output_size, sizeof(int32_t));
-
+	kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t));
 	if (kbd_dev->led_data == NULL) {
-		usb_log_warning("Error creating buffer for LED output report."
-		    "\n");
-		free(kbd_dev->keys);
-		usb_hid_report_output_free(kbd_dev->output_buffer);
-		free(kbd_dev);
+		usb_log_error("Error creating buffer for LED output report.\n");
+		usb_kbd_destroy(kbd_dev);
 		return ENOMEM;
 	}
 
-	/*
-	 * Modifiers and locks
-	 */
-	kbd_dev->modifiers = 0;
-	kbd_dev->mods = DEFAULT_ACTIVE_MODS;
-	kbd_dev->lock_keys = 0;
-
-	/*
-	 * Autorepeat
-	 */
-	kbd_dev->repeat.key_new = 0;
-	kbd_dev->repeat.key_repeated = 0;
-	kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
-	kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
-
-	fibril_mutex_initialize(&kbd_dev->repeat_mtx);
-
-	// save the KBD device structure into the HID device structure
+	/* Set LEDs according to initial setup.
+	 * Set Idle rate */
+	usb_kbd_set_led(hid_dev, kbd_dev);
+
+	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
+	    hid_dev->usb_dev->interface_no, IDLE_RATE);
+
+	/* Save the KBD device structure into the HID device structure. */
 	*data = kbd_dev;
 
-	// set handler for incoming calls
-	kbd_dev->ops.default_handler = default_connection_handler;
-
-	/*
-	 * Set LEDs according to initial setup.
-	 * Set Idle rate
-	 */
-	usb_kbd_set_led(hid_dev, kbd_dev);
-
-	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
-	    hid_dev->usb_dev->interface_no, IDLE_RATE);
-
-	/*
-	 * Create new fibril for auto-repeat
-	 */
+	kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
+	usb_log_debug("HID/KBD device structure initialized.\n");
+
+	usb_log_debug("Creating KBD function...\n");
+	ret = usb_kbd_create_function(kbd_dev);
+	if (ret != EOK) {
+		usb_kbd_destroy(kbd_dev);
+		return ret;
+	}
+
+	/* Create new fibril for auto-repeat. */
 	fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
 	if (fid == 0) {
 		usb_log_error("Failed to start fibril for KBD auto-repeat");
+		usb_kbd_destroy(kbd_dev);
 		return ENOMEM;
 	}
 	fibril_add_ready(fid);
 
-	kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
-	usb_log_debug("HID/KBD device structure initialized.\n");
-
-	usb_log_debug("Creating KBD function...\n");
-	int rc = usb_kbd_create_function(kbd_dev);
-	if (rc != EOK) {
-		usb_kbd_destroy(kbd_dev);
-		return rc;
-	}
-
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
-	if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
-		// do not continue polling (???)
+	if (hid_dev == NULL || data == NULL) {
+		/* This means something serious */
 		return false;
 	}
 
-	usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
-	assert(kbd_dev != NULL);
-
+	usb_kbd_t *kbd_dev = data;
 	// TODO: add return value from this function
 	usb_kbd_process_data(hid_dev, kbd_dev);
@@ -746,19 +714,14 @@
 	return true;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
 {
 	return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
 {
 	return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
 }
-
 /*----------------------------------------------------------------------------*/
 /**
@@ -773,6 +736,7 @@
 	}
 
-	// hangup session to the console
-	async_hangup(kbd_dev->console_sess);
+	/* Hangup session to the console. */
+	if (kbd_dev->console_sess)
+		async_hangup(kbd_dev->console_sess);
 
 	//assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
@@ -781,51 +745,44 @@
 	while (fibril_mutex_is_locked(&kbd_dev->repeat_mtx)) {}
 
-	// free all buffers
+	/* Free all buffers. */
 	free(kbd_dev->keys);
 	free(kbd_dev->keys_old);
 	free(kbd_dev->led_data);
 
-	if (kbd_dev->led_path != NULL) {
-		usb_hid_report_path_free(kbd_dev->led_path);
-	}
-	if (kbd_dev->output_buffer != NULL) {
-		usb_hid_report_output_free(kbd_dev->output_buffer);
-	}
-
-	if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
-		usb_log_warning("Failed to unbind kbd function.\n");
-	} else {
-		usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
-		kbd_dev->fun->driver_data = NULL;
-		ddf_fun_destroy(kbd_dev->fun);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
+	usb_hid_report_path_free(kbd_dev->led_path);
+	usb_hid_report_output_free(kbd_dev->output_buffer);
+
+	if (kbd_dev->fun) {
+		if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
+			usb_log_warning("Failed to unbind %s.\n",
+			    kbd_dev->fun->name);
+		} else {
+			usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
+			kbd_dev->fun->driver_data = NULL;
+			ddf_fun_destroy(kbd_dev->fun);
+		}
+	}
+	free(kbd_dev);
+}
+/*----------------------------------------------------------------------------*/
 void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
-	if (hid_dev == NULL) {
-		return;
-	}
-
 	if (data != NULL) {
 		usb_kbd_t *kbd_dev = data;
 		if (usb_kbd_is_initialized(kbd_dev)) {
-			usb_kbd_mark_unusable(kbd_dev);
-			/* wait for autorepeat */
+			kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
+			/* Wait for autorepeat */
 			async_usleep(CHECK_DELAY);
-			usb_kbd_destroy(kbd_dev);
-		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
+		}
+		usb_kbd_destroy(kbd_dev);
+	}
+}
+/*----------------------------------------------------------------------------*/
 int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
 {
+	assert(hid_dev);
 	int rc = usb_hid_parse_report_descriptor(
 	    &hid_dev->report, USB_KBD_BOOT_REPORT_DESCRIPTOR,
-	    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
+	    sizeof(USB_KBD_BOOT_REPORT_DESCRIPTOR));
 
 	if (rc != EOK) {
@@ -846,5 +803,4 @@
 	return EOK;
 }
-
 /**
  * @}
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -135,5 +135,5 @@
 void usb_kbd_destroy(usb_kbd_t *kbd_dev);
 
-void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
+void usb_kbd_push_ev(usb_kbd_t *kbd_dev,
     int type, unsigned int key);
 
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -45,7 +45,4 @@
 #include "kbddev.h"
 
-
-
-/*----------------------------------------------------------------------------*/
 /**
  * Main loop handling the auto-repeat of keys.
@@ -58,12 +55,12 @@
  * If the same key is still pressed, it uses the delay between repeats stored
  * in the keyboard structure to wait until the key should be repeated.
- * 
+ *
  * If the currently repeated key is not pressed any more (
- * usb_kbd_repeat_stop() was called), it stops repeating it and starts 
+ * usb_kbd_repeat_stop() was called), it stops repeating it and starts
  * checking again.
  *
  * @note For accessing the keyboard device auto-repeat information a fibril
  *       mutex (repeat_mtx) from the @a kbd structure is used.
- * 
+ *
  * @param kbd Keyboard device structure.
  */
@@ -75,18 +72,17 @@
 
 	while (true) {
-		// check if the kbd structure is usable
+		/* Check if the kbd structure is usable. */
 		if (!usb_kbd_is_initialized(kbd)) {
 			usb_log_warning("kbd not ready, exiting autorepeat.\n");
 			return;
 		}
-		
+
 		fibril_mutex_lock(&kbd->repeat_mtx);
 
 		if (kbd->repeat.key_new > 0) {
 			if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
-				usb_log_debug2("Repeating key: %u.\n", 
+				usb_log_debug2("Repeating key: %u.\n",
 				    kbd->repeat.key_repeated);
-				// ugly hack with the NULL
-				usb_kbd_push_ev(NULL, kbd, KEY_PRESS, 
+				usb_kbd_push_ev(kbd, KEY_PRESS,
 				    kbd->repeat.key_repeated);
 				delay = kbd->repeat.delay_between;
@@ -106,9 +102,7 @@
 		}
 		fibril_mutex_unlock(&kbd->repeat_mtx);
-		
 		async_usleep(delay);
 	}
 }
-
 /*----------------------------------------------------------------------------*/
 /**
@@ -116,5 +110,5 @@
  *
  * Starts the loop for checking changes in auto-repeat.
- * 
+ *
  * @param arg User-specified argument. Expects pointer to the keyboard device
  *            structure representing the keyboard.
@@ -132,5 +126,5 @@
 	}
 
-	usb_kbd_t *kbd = (usb_kbd_t *)arg;
+	usb_kbd_t *kbd = arg;
 
 	usb_kbd_repeat_loop(kbd);
@@ -138,5 +132,4 @@
 	return EOK;
 }
-
 /*----------------------------------------------------------------------------*/
 /**
@@ -156,5 +149,4 @@
 	fibril_mutex_unlock(&kbd->repeat_mtx);
 }
-
 /*----------------------------------------------------------------------------*/
 /**
@@ -162,5 +154,5 @@
  *
  * @note Only one key is repeated at any time, but this function may be called
- *       even with key that is not currently repeated (in that case nothing 
+ *       even with key that is not currently repeated (in that case nothing
  *       happens).
  *
@@ -176,5 +168,4 @@
 	fibril_mutex_unlock(&kbd->repeat_mtx);
 }
-
 /**
  * @}
Index: uspace/drv/bus/usb/usbhid/main.c
===================================================================
--- uspace/drv/bus/usb/usbhid/main.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/main.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -49,39 +49,33 @@
 
 /**
- * Function for adding a new device of type USB/HID/keyboard.
+ * Callback for passing a new device to the driver.
  *
- * This functions initializes required structures from the device's descriptors
- * and starts new fibril for polling the keyboard for events and another one for
- * handling auto-repeat of keys.
+ * @note Currently, only boot-protocol keyboards are supported by this driver.
  *
- * During initialization, the keyboard is switched into boot protocol, the idle
- * rate is set to 0 (infinity), resulting in the keyboard only reporting event
- * when a key is pressed or released. Finally, the LED lights are turned on 
- * according to the default setup of lock keys.
- *
- * @note By default, the keyboards is initialized with Num Lock turned on and 
- *       other locks turned off.
- * @note Currently supports only boot-protocol keyboards.
- *
- * @param dev Device to add.
+ * @param dev Structure representing the new device.
  * @return Error code.
  */
-static int usb_hid_try_add_device(usb_device_t *dev)
+static int usb_hid_device_add(usb_device_t *dev)
 {
-	assert(dev != NULL);
+	usb_log_debug("%s\n", __FUNCTION__);
 
-	/* Initialize device (get and process descriptors, get address, etc.) */
-	usb_log_debug("Initializing USB/HID device...\n");
+	if (dev == NULL) {
+		usb_log_error("Wrong parameter given for add_device().\n");
+		return EINVAL;
+	}
 
+	if (dev->interface_no < 0) {
+		usb_log_error("Failed to add HID device: endpoints not found."
+		    "\n");
+		return ENOTSUP;
+	}
 	usb_hid_dev_t *hid_dev =
 	    usb_device_data_alloc(dev, sizeof(usb_hid_dev_t));
 	if (hid_dev == NULL) {
-		usb_log_error("Error while creating USB/HID device "
-		    "structure.\n");
+		usb_log_error("Failed to create USB/HID device structure.\n");
 		return ENOMEM;
 	}
 
 	int rc = usb_hid_init(hid_dev, dev);
-
 	if (rc != EOK) {
 		usb_log_error("Failed to initialize USB/HID device.\n");
@@ -92,19 +86,7 @@
 	usb_log_debug("USB/HID device structure initialized.\n");
 
-	/*
-	 * 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
-	 */
-
 	/* Start automated polling function.
 	 * This will create a separate fibril that will query the device
-	 * for the data continuously 
-	 */
+	 * for the data continuously. */
        rc = usb_device_auto_poll(dev,
 	   /* Index of the polling pipe. */
@@ -113,5 +95,5 @@
 	   usb_hid_polling_callback,
 	   /* How much data to request. */
-	   dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
+	   dev->pipes[hid_dev->poll_pipe_index].pipe.max_packet_size,
 	   /* Callback when the polling ends. */
 	   usb_hid_polling_ended_callback,
@@ -126,43 +108,4 @@
 	}
 	hid_dev->running = true;
-
-	/*
-	 * Hurrah, device is initialized.
-	 */
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/**
- * Callback for passing a new device to the driver.
- *
- * @note Currently, only boot-protocol keyboards are supported by this driver.
- *
- * @param dev Structure representing the new device.
- * @return Error code.
- */
-static int usb_hid_device_add(usb_device_t *dev)
-{
-	usb_log_debug("usb_hid_device_add()\n");
-
-	if (dev == NULL) {
-		usb_log_warning("Wrong parameter given for add_device().\n");
-		return EINVAL;
-	}
-
-	if (dev->interface_no < 0) {
-		usb_log_warning("Device is not a supported HID device.\n");
-		usb_log_error("Failed to add HID device: endpoints not found."
-		    "\n");
-		return ENOTSUP;
-	}
-
-	int rc = usb_hid_try_add_device(dev);
-
-	if (rc != EOK) {
-		usb_log_warning("Device is not a supported HID device.\n");
-		usb_log_error("Failed to add HID device: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
 
 	usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
@@ -179,5 +122,7 @@
 static int usb_hid_device_rem(usb_device_t *dev)
 {
-	return EOK;
+	// TODO: Stop device polling
+	// TODO: Call deinit (stops autorepeat too)
+	return ENOTSUP;
 }
 /*----------------------------------------------------------------------------*/
@@ -190,15 +135,17 @@
 static int usb_hid_device_gone(usb_device_t *dev)
 {
+	assert(dev);
+	assert(dev->driver_data);
 	usb_hid_dev_t *hid_dev = dev->driver_data;
-	unsigned tries = 10;
-	while (hid_dev->running) {
+	unsigned tries = 100;
+	/* Wait for fail. */
+	while (hid_dev->running && tries--) {
 		async_usleep(100000);
-		if (!tries--) {
-			usb_log_error("Can't remove hub, still running.\n");
-			return EBUSY;
-		}
+	}
+	if (hid_dev->running) {
+		usb_log_error("Can't remove hid, still running.\n");
+		return EBUSY;
 	}
 
-	assert(!hid_dev->running);
 	usb_hid_deinit(hid_dev);
 	usb_log_debug2("%s destruction complete.\n", dev->ddf_dev->name);
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -55,5 +55,5 @@
 #define ARROWS_PER_SINGLE_WHEEL 3
 
-#define NAME  "mouse"
+#define NAME "mouse"
 
 /*----------------------------------------------------------------------------*/
@@ -77,11 +77,5 @@
 
 /*----------------------------------------------------------------------------*/
-
-enum {
-	USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63
-};
-
-static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[
-    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = {
+static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[] = {
 	0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
 	0x09, 0x02,                    // USAGE (Mouse)
@@ -123,20 +117,17 @@
     ipc_callid_t icallid, ipc_call_t *icall)
 {
-	usb_mouse_t *mouse_dev = (usb_mouse_t *) fun->driver_data;
+	usb_mouse_t *mouse_dev = fun->driver_data;
 
 	if (mouse_dev == NULL) {
-		usb_log_debug("default_connection_handler: Missing "
-		    "parameters.\n");
+		usb_log_debug("%s: Missing parameters.\n", __FUNCTION__);
 		async_answer_0(icallid, EINVAL);
 		return;
 	}
 
-	usb_log_debug("default_connection_handler: fun->name: %s\n",
-	              fun->name);
-	usb_log_debug("default_connection_handler: mouse_sess: %p, "
-	    "wheel_sess: %p\n", mouse_dev->mouse_sess, mouse_dev->wheel_sess);
-
-	async_sess_t **sess_ptr =
-	    (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) ?
+	usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name);
+	usb_log_debug("%s: mouse_sess: %p, wheel_sess: %p\n",
+	    __FUNCTION__, mouse_dev->mouse_sess, mouse_dev->wheel_sess);
+
+	async_sess_t **sess_ptr = (fun == mouse_dev->mouse_fun) ?
 	    &mouse_dev->mouse_sess : &mouse_dev->wheel_sess;
 
@@ -146,58 +137,15 @@
 		if (*sess_ptr == NULL) {
 			*sess_ptr = sess;
-			usb_log_debug("Console session to mouse set ok (%p).\n",
-			    sess);
+			usb_log_debug("Console session to %s set ok (%p).\n",
+			    fun->name, sess);
 			async_answer_0(icallid, EOK);
 		} else {
-			usb_log_debug("default_connection_handler: Console "
-			    "session to mouse already set.\n");
+			usb_log_error("Console session to %s already set.\n",
+			    fun->name);
 			async_answer_0(icallid, ELIMIT);
 		}
 	} else {
-		usb_log_debug("default_connection_handler: Invalid function.\n");
+		usb_log_debug("%s: Invalid function.\n", __FUNCTION__);
 		async_answer_0(icallid, EINVAL);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
-static usb_mouse_t *usb_mouse_new(void)
-{
-	usb_mouse_t *mouse = calloc(1, sizeof(usb_mouse_t));
-	if (mouse == NULL) {
-		return NULL;
-	}
-	mouse->mouse_sess = NULL;
-	mouse->wheel_sess = NULL;
-
-	return mouse;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void usb_mouse_destroy(usb_mouse_t *mouse_dev)
-{
-	assert(mouse_dev != NULL);
-
-	// hangup session to the console
-	if (mouse_dev->mouse_sess != NULL)
-		async_hangup(mouse_dev->mouse_sess);
-
-	if (mouse_dev->wheel_sess != NULL)
-		async_hangup(mouse_dev->wheel_sess);
-	int ret = ddf_fun_unbind(mouse_dev->mouse_fun);
-	if (ret != EOK) {
-		usb_log_error("Failed to unbind mouse function.\n");
-	} else {
-		ddf_fun_destroy(mouse_dev->mouse_fun);
-		/* Prevent double free */
-		mouse_dev->wheel_fun->driver_data = NULL;
-	}
-
-	ret = ddf_fun_unbind(mouse_dev->wheel_fun);
-	if (ret != EOK) {
-		usb_log_error("Failed to unbind wheel function.\n");
-	} else {
-		ddf_fun_destroy(mouse_dev->wheel_fun);
 	}
 }
@@ -215,8 +163,7 @@
 	}
 
-	int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
-	int i;
-
-	for (i = 0; i < count; i++) {
+	const unsigned count =
+	    ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
+	for (unsigned i = 0; i < count; i++) {
 		/* Send arrow press and release. */
 		usb_log_debug2("Sending key %d to the console\n", key);
@@ -267,9 +214,9 @@
 	}
 
-	int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
+	const int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
 	    &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
-	int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
+	const int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
 	    &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
-	int wheel = get_mouse_axis_move_value(hid_dev->report_id,
+	const int wheel = get_mouse_axis_move_value(hid_dev->report_id,
 	    &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
 
@@ -277,6 +224,8 @@
 		async_exch_t *exch =
 		    async_exchange_begin(mouse_dev->mouse_sess);
-		async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
-		async_exchange_end(exch);
+		if (exch != NULL) {
+			async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
+			async_exchange_end(exch);
+		}
 	}
 
@@ -284,9 +233,17 @@
 		usb_mouse_send_wheel(mouse_dev, wheel);
 
-	/*
-	 * Buttons
-	 */
+	/* Buttons */
 	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
+	if (path == NULL) {
+		usb_log_warning("Failed to create USB HID report path.\n");
+		return true;
+	}
+	int ret =
+	   usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
+	if (ret != EOK) {
+		usb_hid_report_path_free(path);
+		usb_log_warning("Failed to add buttons to report path.\n");
+		return true;
+	}
 	usb_hid_report_path_set_report_id(path, hid_dev->report_id);
 
@@ -298,23 +255,27 @@
 		usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
 		    field->usage);
-		
-		if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
-		    && field->value != 0) {
+		assert(field->usage > field->usage_minimum);
+		const unsigned index = field->usage - field->usage_minimum;
+		assert(index < mouse_dev->buttons_count);
+
+		if (mouse_dev->buttons[index] == 0 && field->value != 0) {
 			async_exch_t *exch =
 			    async_exchange_begin(mouse_dev->mouse_sess);
-			async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 1);
-			async_exchange_end(exch);
-			
-			mouse_dev->buttons[field->usage - field->usage_minimum]
-			    = field->value;
-		} else if (mouse_dev->buttons[field->usage - field->usage_minimum] != 0
-		    && field->value == 0) {
+			if (exch != NULL) {
+				async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
+				    field->usage, 1);
+				async_exchange_end(exch);
+				mouse_dev->buttons[index] = field->value;
+			}
+
+		} else if (mouse_dev->buttons[index] != 0 && field->value == 0) {
 			async_exch_t *exch =
 			    async_exchange_begin(mouse_dev->mouse_sess);
-			async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 0);
-			async_exchange_end(exch);
-
-			mouse_dev->buttons[field->usage - field->usage_minimum] =
-			   field->value;
+			if (exch != NULL) {
+				async_req_2_0(exch, MOUSEEV_BUTTON_EVENT,
+				    field->usage, 0);
+				async_exchange_end(exch);
+				mouse_dev->buttons[index] = field->value;
+			}
 		}
 
@@ -329,7 +290,16 @@
 	return true;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
+#define FUN_UNBIND_DESTROY(fun) \
+if (fun) { \
+	if (ddf_fun_unbind((fun)) == EOK) { \
+		(fun)->driver_data = NULL; \
+		ddf_fun_destroy((fun)); \
+	} else { \
+		usb_log_error("Could not unbind function `%s', it " \
+		    "will not be destroyed.\n", (fun)->name); \
+	} \
+} else (void)0
+/*----------------------------------------------------------------------------*/
 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
 {
@@ -339,8 +309,9 @@
 	/* Create the exposed function. */
 	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, 
+	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");
+		usb_log_error("Could not create DDF function node `%s'.\n",
+		    HID_MOUSE_FUN_NAME);
 		return ENOMEM;
 	}
@@ -351,11 +322,13 @@
 	int rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	usb_log_debug("Adding DDF function to category %s...\n", 
-	    HID_MOUSE_CATEGORY);
+		usb_log_error("Could not bind DDF function `%s': %s.\n",
+		    fun->name, str_error(rc));
+		fun->driver_data = NULL;
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	usb_log_debug("Adding DDF function `%s' to category %s...\n",
+	    fun->name, HID_MOUSE_CATEGORY);
 	rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
 	if (rc != EOK) {
@@ -363,4 +336,5 @@
 		    "Could not add DDF function to category %s: %s.\n",
 		    HID_MOUSE_CATEGORY, str_error(rc));
+		FUN_UNBIND_DESTROY(fun);
 		return rc;
 	}
@@ -370,10 +344,13 @@
 	 * Special function for acting as keyboard (wheel)
 	 */
-	usb_log_debug("Creating DDF function %s...\n", 
+	usb_log_debug("Creating DDF function %s...\n",
 	              HID_MOUSE_WHEEL_FUN_NAME);
-	fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
 	    HID_MOUSE_WHEEL_FUN_NAME);
 	if (fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
+		usb_log_error("Could not create DDF function node `%s'.\n",
+		    HID_MOUSE_WHEEL_FUN_NAME);
+		FUN_UNBIND_DESTROY(mouse->mouse_fun);
+		mouse->mouse_fun = NULL;
 		return ENOMEM;
 	}
@@ -388,6 +365,11 @@
 	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
+		usb_log_error("Could not bind DDF function `%s': %s.\n",
+		    fun->name, str_error(rc));
+		FUN_UNBIND_DESTROY(mouse->mouse_fun);
+		mouse->mouse_fun = NULL;
+
+		fun->driver_data = NULL;
+		ddf_fun_destroy(fun);
 		return rc;
 	}
@@ -400,4 +382,8 @@
 		    "Could not add DDF function to category %s: %s.\n",
 		    HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
+
+		FUN_UNBIND_DESTROY(mouse->mouse_fun);
+		mouse->mouse_fun = NULL;
+		FUN_UNBIND_DESTROY(fun);
 		return rc;
 	}
@@ -448,7 +434,5 @@
 	return highest_button;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
 {
@@ -461,5 +445,5 @@
 	}
 
-	usb_mouse_t *mouse_dev = usb_mouse_new();
+	usb_mouse_t *mouse_dev = calloc(1, sizeof(usb_mouse_t));
 	if (mouse_dev == NULL) {
 		usb_log_error("Error while creating USB/HID Mouse device "
@@ -484,55 +468,71 @@
 	}
 
-
-	// save the Mouse device structure into the HID device structure
-	*data = mouse_dev;
-
 	// set handler for incoming calls
 	mouse_dev->ops.default_handler = default_connection_handler;
 
 	// TODO: how to know if the device supports the request???
-	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
+	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, mouse_dev);
 	if (rc != EOK) {
-		usb_mouse_destroy(mouse_dev);
-		return rc;
-	}
+		free(mouse_dev->buttons);
+		free(mouse_dev);
+		return rc;
+	}
+
+	/* Save the Mouse device structure into the HID device structure. */
+	*data = mouse_dev;
 
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
 {
 	if (hid_dev == NULL || data == NULL) {
-		usb_log_error("Missing argument to the mouse polling callback."
-		    "\n");
+		usb_log_error(
+		    "Missing argument to the mouse polling callback.\n");
 		return false;
 	}
 
-	usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
-		
+	usb_mouse_t *mouse_dev = data;
+
 	return usb_mouse_process_report(hid_dev, mouse_dev);
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
 {
-	if (data != NULL) {
-		usb_mouse_destroy(data);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
+	if (data == NULL)
+		return;
+
+	usb_mouse_t *mouse_dev = data;
+
+	/* Hangup session to the console */
+	if (mouse_dev->mouse_sess != NULL) {
+		const int ret = async_hangup(mouse_dev->mouse_sess);
+		if (ret != EOK)
+			usb_log_warning("Failed to hang up mouse session: "
+			    "%p, %s.\n", mouse_dev->mouse_sess, str_error(ret));
+	}
+
+	if (mouse_dev->wheel_sess != NULL) {
+		const int ret = async_hangup(mouse_dev->wheel_sess);
+		if (ret != EOK)
+			usb_log_warning("Failed to hang up wheel session: "
+			    "%p, %s.\n", mouse_dev->wheel_sess, str_error(ret));
+	}
+
+	FUN_UNBIND_DESTROY(mouse_dev->mouse_fun);
+	FUN_UNBIND_DESTROY(mouse_dev->wheel_fun);
+
+	free(mouse_dev->buttons);
+	free(mouse_dev);
+}
+/*----------------------------------------------------------------------------*/
 int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
 {
 	int rc = usb_hid_parse_report_descriptor(
 	    &hid_dev->report, USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
-	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
+	    sizeof(USB_MOUSE_BOOT_REPORT_DESCRIPTOR));
 
 	if (rc != EOK) {
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -67,11 +67,9 @@
 	/** IPC session to the console device (for sending key events). */
 	async_sess_t *console_sess;
-	/** DDF function */
-	ddf_fun_t *fun;
 } usb_multimedia_t;
 
 
 /*----------------------------------------------------------------------------*/
-/** 
+/**
  * Default handler for IPC methods not handled by DDF.
  *
@@ -88,11 +86,10 @@
 {
 	usb_log_debug(NAME " default_connection_handler()\n");
-
-	usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
-
-	if (multim_dev == NULL) {
+	if (fun == NULL || fun->driver_data == NULL) {
 		async_answer_0(icallid, EINVAL);
 		return;
 	}
+
+	usb_multimedia_t *multim_dev = fun->driver_data;
 
 	async_sess_t *sess =
@@ -109,11 +106,8 @@
 		async_answer_0(icallid, EINVAL);
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static ddf_dev_ops_t multimedia_ops = {
 	.default_handler = default_connection_handler
 };
-
 /*----------------------------------------------------------------------------*/
 /**
@@ -127,23 +121,22 @@
  *       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: 
+ *
+ * @param hid_dev
+ * @param multim_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, 
+static void usb_multimedia_push_ev(
     usb_multimedia_t *multim_dev, int type, unsigned int key)
 {
-	assert(hid_dev != NULL);
 	assert(multim_dev != NULL);
 
-	kbd_event_t ev;
-
-	ev.type = type;
-	ev.key = key;
-	ev.mods = 0;
-	ev.c = 0;
+	const kbd_event_t ev = {
+		.type = type,
+		.key = key,
+		.mods = 0,
+		.c = 0,
+	};
 
 	usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
@@ -155,14 +148,16 @@
 
 	async_exch_t *exch = async_exchange_begin(multim_dev->console_sess);
-	async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
-	async_exchange_end(exch);
-}
-
-/*----------------------------------------------------------------------------*/
-
+	if (exch != NULL) {
+		async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
+		async_exchange_end(exch);
+	} else {
+		usb_log_warning("Failed to send multimedia key.\n");
+	}
+}
+/*----------------------------------------------------------------------------*/
 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
 {
 	if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
-		return EINVAL; /*! @todo Other return code? */
+		return EINVAL;
 	}
 
@@ -187,5 +182,4 @@
 
 	multim_dev->console_sess = NULL;
-	multim_dev->fun = fun;
 
 	//todo Autorepeat?
@@ -199,6 +193,6 @@
 	}
 
-	usb_log_debug("%s function created (handle: %" PRIun ").\n",
-	    NAME, fun->handle);
+	usb_log_debug(NAME " function created (handle: %" PRIun ").\n",
+	    fun->handle);
 
 	rc = ddf_fun_add_to_category(fun, "keyboard");
@@ -207,50 +201,63 @@
 		    "Could not add DDF function to category 'keyboard': %s.\n",
 		    str_error(rc));
-		ddf_fun_destroy(fun);
+		if (ddf_fun_unbind(fun) != EOK) {
+			usb_log_error("Failed to unbind %s, won't destroy.\n",
+			    fun->name);
+		} else {
+			ddf_fun_destroy(fun);
+		}
 		return rc;
 	}
 
 	/* Save the KBD device structure into the HID device structure. */
-	*data = multim_dev;
+	*data = fun;
 
 	usb_log_debug(NAME " HID/multimedia structure initialized.\n");
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
 {
-	if (hid_dev == NULL) {
-		return;
-	}
-
-	if (data != NULL) {
-		usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
-		// hangup session to the console
-		async_hangup(multim_dev->console_sess);
-		const int ret = ddf_fun_unbind(multim_dev->fun);
-		if (ret != EOK) {
-			usb_log_error("Failed to unbind multim function.\n");
+	ddf_fun_t *fun = data;
+	if (fun != NULL && fun->driver_data != NULL) {
+		usb_multimedia_t *multim_dev = fun->driver_data;
+		/* Hangup session to the console */
+		if (multim_dev->console_sess)
+			async_hangup(multim_dev->console_sess);
+		if (ddf_fun_unbind(fun) != EOK) {
+			usb_log_error("Failed to unbind %s, won't destroy.\n",
+			    fun->name);
 		} else {
-			usb_log_debug2("%s unbound.\n", multim_dev->fun->name);
-			ddf_fun_destroy(multim_dev->fun);
+			usb_log_debug2("%s unbound.\n", fun->name);
+			/* This frees multim_dev too as it was stored in
+			 * fun->data */
+			ddf_fun_destroy(fun);
 		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
+	} else {
+		usb_log_error(
+		    "Failed to deinit multimedia subdriver, data missing.\n");
+	}
+}
+/*----------------------------------------------------------------------------*/
 bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
 {
 	// TODO: checks
-	if (hid_dev == NULL || data == NULL) {
+	ddf_fun_t *fun = data;
+	if (hid_dev == NULL || fun == NULL || fun->driver_data == NULL) {
 		return false;
 	}
 
-	usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
+	usb_multimedia_t *multim_dev = fun->driver_data;
 
 	usb_hid_report_path_t *path = usb_hid_report_path();
-	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
+	if (path == NULL)
+		return true; /* This might be a temporary failure. */
+
+	int ret =
+	    usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
+	if (ret != EOK) {
+		usb_hid_report_path_free(path);
+		return true; /* This might be a temporary failure. */
+	}
 
 	usb_hid_report_path_set_report_id(path, hid_dev->report_id);
@@ -261,23 +268,21 @@
 	    USB_HID_REPORT_TYPE_INPUT);
 
-	/*! @todo Is this iterating OK if done multiple times? 
-	 *  @todo The parsing is not OK
-	 */
+	//FIXME Is this iterating OK if done multiple times?
+	//FIXME The parsing is not OK. (what's wrong?)
 	while (field != NULL) {
-		if(field->value != 0) {
-			usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
+		if (field->value != 0) {
+			usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n",
 			    field->value, field->usage);
-			unsigned int key = 
+			const unsigned key =
 			    usb_multimedia_map_usage(field->usage);
-			const char *key_str = 
+			const char *key_str =
 			    usbhid_multimedia_usage_to_str(field->usage);
 			usb_log_info("Pressed key: %s\n", key_str);
-			usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS, 
-			                       key);
+			usb_multimedia_push_ev(multim_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_PATH_COMPARE_USAGE_PAGE_ONLY,
 		    USB_HID_REPORT_TYPE_INPUT);
 	}
@@ -287,5 +292,4 @@
 	return true;
 }
-
 /**
  * @}
Index: uspace/drv/bus/usb/usbhid/subdrivers.c
===================================================================
--- uspace/drv/bus/usb/usbhid/subdrivers.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/subdrivers.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -98,8 +98,7 @@
 		}
 	},
-	{NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL, NULL}}
 };
 
-const int USB_HID_MAX_SUBDRIVERS =
+const size_t USB_HID_MAX_SUBDRIVERS =
     sizeof(usb_hid_subdrivers) / sizeof(usb_hid_subdrivers[0]);
 
Index: uspace/drv/bus/usb/usbhid/subdrivers.h
===================================================================
--- uspace/drv/bus/usb/usbhid/subdrivers.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/subdrivers.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -84,5 +84,5 @@
 
 extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
-extern const int USB_HID_MAX_SUBDRIVERS;
+extern const size_t USB_HID_MAX_SUBDRIVERS;
 
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/bus/usb/usbhid/usbhid.c
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/usbhid.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -51,6 +51,4 @@
 #include "subdrivers.h"
 
-/*----------------------------------------------------------------------------*/
-
 /* Array of endpoints expected on the device, NULL terminated. */
 const usb_endpoint_description_t *usb_hid_endpoints[] = {
@@ -60,7 +58,5 @@
 	NULL
 };
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
 {
@@ -78,7 +74,5 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
 {
@@ -92,14 +86,13 @@
 	hid_dev->subdriver_count = 1;
 	// TODO 2 should be mouse, but find a better way
-	hid_dev->subdrivers[2] = usb_hid_subdrivers[0].subdriver;
+	hid_dev->subdrivers[0] = usb_hid_subdrivers[2].subdriver;
 
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
 {
-	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
+	assert(hid_dev != NULL);
+	assert(hid_dev->subdriver_count == 0);
 
 	hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t));
@@ -117,7 +110,5 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev,
     const usb_hid_subdriver_mapping_t *mapping)
@@ -128,10 +119,8 @@
 	return (hid_dev->usb_dev->descriptors.device.vendor_id
 	    == mapping->vendor_id
-	    && hid_dev->usb_dev->descriptors.device.product_id 
+	    && hid_dev->usb_dev->descriptors.device.product_id
 	    == mapping->product_id);
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
     const usb_hid_subdriver_mapping_t *mapping)
@@ -145,7 +134,7 @@
 		return false;
 	}
-	int i = 0;
-	while (mapping->usage_path[i].usage != 0
-	    || mapping->usage_path[i].usage_page != 0) {
+
+	for (int i = 0; mapping->usage_path[i].usage != 0
+	    || mapping->usage_path[i].usage_page != 0; ++i) {
 		if (usb_hid_report_path_append_item(usage_path,
 		    mapping->usage_path[i].usage_page,
@@ -155,5 +144,4 @@
 			return false;
 		}
-		++i;
 	}
 
@@ -165,5 +153,4 @@
 	do {
 		usb_log_debug("Trying report id %u\n", report_id);
-
 		if (report_id != 0) {
 			usb_hid_report_path_set_report_id(usage_path,
@@ -171,7 +158,8 @@
 		}
 
-		usb_hid_report_field_t *field = usb_hid_report_get_sibling(
-		    &hid_dev->report, NULL, usage_path, mapping->compare,
-		    USB_HID_REPORT_TYPE_INPUT);
+		const usb_hid_report_field_t *field =
+		    usb_hid_report_get_sibling(
+		        &hid_dev->report, NULL, usage_path, mapping->compare,
+		        USB_HID_REPORT_TYPE_INPUT);
 
 		usb_log_debug("Field: %p\n", field);
@@ -190,13 +178,12 @@
 	return matches;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
-    const usb_hid_subdriver_t **subdrivers, int count)
-{
-	int i;
-
-	if (count <= 0) {
+    const usb_hid_subdriver_t **subdrivers, unsigned count)
+{
+	assert(hid_dev);
+	assert(subdrivers);
+
+	if (count == 0) {
 		hid_dev->subdriver_count = 0;
 		hid_dev->subdrivers = NULL;
@@ -210,9 +197,6 @@
 	}
 
-	for (i = 0; i < count; ++i) {
-		hid_dev->subdrivers[i].init = subdrivers[i]->init;
-		hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
-		hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
-		hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
+	for (unsigned i = 0; i < count; ++i) {
+		hid_dev->subdrivers[i] = *subdrivers[i];
 	}
 
@@ -227,7 +211,5 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
 {
@@ -235,31 +217,23 @@
 
 	const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
-
-	int i = 0, count = 0;
-	const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
-
-	bool ids_matched;
-	bool matched;
-
-	while (count < USB_HID_MAX_SUBDRIVERS &&
-	    (mapping->usage_path != NULL
-	    || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
-		// check the vendor & product ID
+	unsigned count = 0;
+
+	for (unsigned i = 0; i < USB_HID_MAX_SUBDRIVERS; ++i) {
+		const usb_hid_subdriver_mapping_t *mapping =
+		    &usb_hid_subdrivers[i];
+		/* Check the vendor & product ID. */
 		if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
-			usb_log_warning("Missing Product ID for Vendor ID %d\n",
-			    mapping->vendor_id);
-			return EINVAL;
+			usb_log_warning("Mapping[%d]: Missing Product ID for "
+			    "Vendor ID %d\n", i, mapping->vendor_id);
 		}
 		if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
-			usb_log_warning("Missing Vendor ID for Product ID %d\n",
-			    mapping->product_id);
-			return EINVAL;
-		}
-
-		ids_matched = false;
-		matched = false;
-
-		if (mapping->vendor_id >= 0) {
-			assert(mapping->product_id >= 0);
+			usb_log_warning("Mapping[%d]: Missing Vendor ID for "
+			    "Product ID %d\n", i, mapping->product_id);
+		}
+
+		bool matched = false;
+
+		/* Check ID match. */
+		if (mapping->vendor_id >= 0 && mapping->product_id >= 0) {
 			usb_log_debug("Comparing device against vendor ID %u"
 			    " and product ID %u.\n", mapping->vendor_id,
@@ -267,17 +241,15 @@
 			if (usb_hid_ids_match(hid_dev, mapping)) {
 				usb_log_debug("IDs matched.\n");
-				ids_matched = true;
+				matched = true;
 			}
 		}
 
+		/* Check usage match. */
 		if (mapping->usage_path != NULL) {
 			usb_log_debug("Comparing device against usage path.\n");
 			if (usb_hid_path_matches(hid_dev, mapping)) {
-				// does not matter if IDs were matched
+				/* Does not matter if IDs were matched. */
 				matched = true;
 			}
-		} else {
-			// matched only if IDs were matched and there is no path
-			matched = ids_matched;
 		}
 
@@ -286,16 +258,10 @@
 			subdrivers[count++] = &mapping->subdriver;
 		}
-
-		mapping = &usb_hid_subdrivers[++i];
 	}
 
 	/* We have all subdrivers determined, save them into the hid device */
-	// TODO Dowe really need this complicated stuff if there is
-	// max_subdrivers limitation?
 	return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev)
 {
@@ -303,27 +269,26 @@
 	assert(dev);
 
-	if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
-		usb_log_debug("Found keyboard endpoint.\n");
-		// save the pipe index
-		hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
-	} else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
-		usb_log_debug("Found mouse endpoint.\n");
-		// save the pipe index
-		hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
-	} else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
-		usb_log_debug("Found generic HID endpoint.\n");
-		// save the pipe index
-		hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
-	} else {
-		usb_log_error("None of supported endpoints found - probably"
-		    " not a supported device.\n");
-		return ENOTSUP;
-	}
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
+	static const struct {
+		unsigned ep_number;
+		const char* description;
+	} endpoints[] = {
+		{USB_HID_KBD_POLL_EP_NO, "Keyboard endpoint"},
+		{USB_HID_MOUSE_POLL_EP_NO, "Mouse endpoint"},
+		{USB_HID_GENERIC_POLL_EP_NO, "Generic HID endpoint"},
+	};
+
+	for (unsigned i = 0; i < sizeof(endpoints)/sizeof(endpoints[0]); ++i) {
+		if (endpoints[i].ep_number >= dev->pipes_count) {
+			return EINVAL;
+		}
+		if (dev->pipes[endpoints[i].ep_number].present) {
+			usb_log_debug("Found: %s.\n", endpoints[i].description);
+			hid_dev->poll_pipe_index = endpoints[i].ep_number;
+			return EOK;
+		}
+	}
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
 static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
 {
@@ -357,24 +322,28 @@
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
+/*
+ * This functions initializes required structures from the device's descriptors
+ * and starts new fibril for polling the keyboard for events and another one for
+ * handling auto-repeat of keys.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ *
+ * @param hid_dev Device to initialize, non-NULL.
+ * @param dev USB device, non-NULL.
+ * @return Error code.
+ */
 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
 {
-	int rc, i;
+	assert(hid_dev);
+	assert(dev);
 
 	usb_log_debug("Initializing HID structure...\n");
-
-	if (hid_dev == NULL) {
-		usb_log_error("Failed to init HID structure: no structure given"
-		    ".\n");
-		return EINVAL;
-	}
-
-	if (dev == NULL) {
-		usb_log_error("Failed to init HID structure: no USB device"
-		    " given.\n");
-		return EINVAL;
-	}
 
 	usb_hid_report_init(&hid_dev->report);
@@ -384,5 +353,5 @@
 	hid_dev->poll_pipe_index = -1;
 
-	rc = usb_hid_check_pipes(hid_dev, dev);
+	int rc = usb_hid_check_pipes(hid_dev, dev);
 	if (rc != EOK) {
 		return rc;
@@ -390,28 +359,26 @@
 
 	/* Get the report descriptor and parse it. */
-	rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
-	    &hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
-
-	bool fallback = false;
-
+	rc = usb_hid_process_report_descriptor(
+	    hid_dev->usb_dev, &hid_dev->report, &hid_dev->report_desc,
+	    &hid_dev->report_desc_size);
+
+	/* If report parsing went well, find subdrivers. */
 	if (rc == EOK) {
-		// try to find subdrivers that may want to handle this device
-		rc = usb_hid_find_subdrivers(hid_dev);
-		if (rc != EOK || hid_dev->subdriver_count == 0) {
-			// try to fall back to the boot protocol if available
-			usb_log_info("No subdrivers found to handle this"
-			    " device.\n");
-			fallback = true;
-			assert(hid_dev->subdrivers == NULL);
-			assert(hid_dev->subdriver_count == 0);
-		}
+		usb_hid_find_subdrivers(hid_dev);
 	} else {
-		usb_log_error("Failed to parse Report descriptor.\n");
-		// try to fall back to the boot protocol if available
-		fallback = true;
-	}
-
-	if (fallback) {
-		// fall back to boot protocol
+		usb_log_error("Failed to parse report descriptor: fallback.\n");
+		hid_dev->subdrivers = NULL;
+		hid_dev->subdriver_count = 0;
+	}
+
+	usb_log_debug("Subdriver count(before trying boot protocol): %d\n",
+	    hid_dev->subdriver_count);
+
+	/* No subdrivers, fall back to the boot protocol if available. */
+	if (hid_dev->subdriver_count == 0) {
+		assert(hid_dev->subdrivers == NULL);
+		usb_log_info("No subdrivers found to handle device, trying "
+		    "boot protocol.\n");
+
 		switch (hid_dev->poll_pipe_index) {
 		case USB_HID_KBD_POLL_EP_NO:
@@ -419,5 +386,5 @@
 			rc = usb_kbd_set_boot_protocol(hid_dev);
 			if (rc == EOK) {
-				rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
+				usb_hid_set_boot_kbd_subdriver(hid_dev);
 			}
 			break;
@@ -426,5 +393,5 @@
 			rc = usb_mouse_set_boot_protocol(hid_dev);
 			if (rc == EOK) {
-				rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
+				usb_hid_set_boot_mouse_subdriver(hid_dev);
 			}
 			break;
@@ -432,44 +399,54 @@
 			assert(hid_dev->poll_pipe_index
 			    == USB_HID_GENERIC_POLL_EP_NO);
-
 			usb_log_info("Falling back to generic HID driver.\n");
-			rc = usb_hid_set_generic_hid_subdriver(hid_dev);
-		}
-	}
-
-	if (rc != EOK) {
-		usb_log_error("No subdriver for handling this device could be"
-		    " initialized: %s.\n", str_error(rc));
-		usb_log_debug("Subdriver count: %d\n",
-		    hid_dev->subdriver_count);
-	} else {
-		bool ok = false;
-
-		usb_log_debug("Subdriver count: %d\n",
-		    hid_dev->subdriver_count);
-
-		for (i = 0; i < hid_dev->subdriver_count; ++i) {
-			if (hid_dev->subdrivers[i].init != NULL) {
-				usb_log_debug("Initializing subdriver %d.\n",i);
-				rc = hid_dev->subdrivers[i].init(hid_dev,
-				    &hid_dev->subdrivers[i].data);
-				if (rc != EOK) {
-					usb_log_warning("Failed to initialize"
-					    " HID subdriver structure.\n");
-				} else {
-					// at least one subdriver initialized
-					ok = true;
-				}
+			usb_hid_set_generic_hid_subdriver(hid_dev);
+		}
+	}
+
+	usb_log_debug("Subdriver count(after trying boot protocol): %d\n",
+	    hid_dev->subdriver_count);
+
+	/* Still no subdrivers? */
+	if (hid_dev->subdriver_count == 0) {
+		assert(hid_dev->subdrivers == NULL);
+		usb_log_error(
+		    "No subdriver for handling this device could be found.\n");
+		return ENOTSUP;
+	}
+
+	/*
+	 * 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
+	 */
+	bool ok = false;
+	for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
+		if (hid_dev->subdrivers[i].init != NULL) {
+			usb_log_debug("Initializing subdriver %d.\n",i);
+			const int pret = hid_dev->subdrivers[i].init(hid_dev,
+			    &hid_dev->subdrivers[i].data);
+			if (pret != EOK) {
+				usb_log_warning("Failed to initialize"
+				    " HID subdriver structure: %s.\n",
+				    str_error(pret));
+				rc = pret;
 			} else {
+				/* At least one subdriver initialized. */
 				ok = true;
 			}
-		}
-
-		rc = (ok) ? EOK : -1;	// what error to report
-	}
-
-
-	if (rc == EOK) {
-		// save max input report size and allocate space for the report
+		} else {
+			/* Does not need initialization. */
+			ok = true;
+		}
+	}
+
+	if (ok) {
+		/* Save max input report size and
+		 * allocate space for the report */
 		rc = usb_hid_init_report(hid_dev);
 		if (rc != EOK) {
@@ -481,7 +458,5 @@
 	return rc;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     size_t buffer_size, void *arg)
@@ -516,5 +491,5 @@
 	bool cont = false;
 	/* Continue if at least one of the subdrivers want to continue */
-	for (int i = 0; i < hid_dev->subdriver_count; ++i) {
+	for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
 		if (hid_dev->subdrivers[i].poll != NULL) {
 			cont = cont || hid_dev->subdrivers[i].poll(
@@ -525,7 +500,5 @@
 	return cont;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
 {
@@ -535,5 +508,5 @@
 	usb_hid_dev_t *hid_dev = arg;
 
-	for (int i = 0; i < hid_dev->subdriver_count; ++i) {
+	for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
 		if (hid_dev->subdrivers[i].poll_end != NULL) {
 			hid_dev->subdrivers[i].poll_end(
@@ -544,21 +517,15 @@
 	hid_dev->running = false;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 void usb_hid_new_report(usb_hid_dev_t *hid_dev)
 {
 	++hid_dev->report_nr;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 int usb_hid_report_number(const usb_hid_dev_t *hid_dev)
 {
 	return hid_dev->report_nr;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 void usb_hid_deinit(usb_hid_dev_t *hid_dev)
 {
@@ -570,5 +537,5 @@
 	    hid_dev->subdrivers, hid_dev->subdriver_count);
 
-	for (int i = 0; i < hid_dev->subdriver_count; ++i) {
+	for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) {
 		if (hid_dev->subdrivers[i].deinit != NULL) {
 			hid_dev->subdrivers[i].deinit(hid_dev,
Index: uspace/drv/bus/usb/usbhid/usbhid.h
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhid/usbhid.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -104,5 +104,5 @@
 
 	/** Index of the polling pipe in usb_hid_endpoints array. */
-	int poll_pipe_index;
+	unsigned poll_pipe_index;
 
 	/** Subdrivers. */
@@ -110,5 +110,5 @@
 
 	/** Number of subdrivers. */
-	int subdriver_count;
+	unsigned subdriver_count;
 
 	/** Report descriptor. */
Index: uspace/drv/bus/usb/usbhub/port.c
===================================================================
--- uspace/drv/bus/usb/usbhub/port.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhub/port.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -401,4 +401,5 @@
 {
 	usb_hub_port_t *port = arg;
+	assert(port);
 	const int rc =
 	    usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET);
@@ -440,21 +441,20 @@
 	    data->port, &new_address, NULL, NULL, &child_fun);
 
-	if (rc != EOK) {
+	if (rc == EOK) {
+		fibril_mutex_lock(&data->port->mutex);
+		data->port->attached_device.fun = child_fun;
+		data->port->attached_device.address = new_address;
+		fibril_mutex_unlock(&data->port->mutex);
+
+		usb_log_info("Detected new device on `%s' (port %zu), "
+		    "address %d (handle %" PRIun ").\n",
+		    data->hub->usb_device->ddf_dev->name,
+		    data->port->port_number, new_address, child_fun->handle);
+	} else {
 		usb_log_error("Failed registering device on port %zu: %s.\n",
 		    data->port->port_number, str_error(rc));
-		goto leave;
-	}
-
-	fibril_mutex_lock(&data->port->mutex);
-	data->port->attached_device.fun = child_fun;
-	data->port->attached_device.address = new_address;
-	fibril_mutex_unlock(&data->port->mutex);
-
-	usb_log_info("Detected new device on `%s' (port %zu), "
-	    "address %d (handle %" PRIun ").\n",
-	    data->hub->usb_device->ddf_dev->name, data->port->port_number,
-	    new_address, child_fun->handle);
-
-leave:
+	}
+
+
 	fibril_mutex_lock(&data->hub->pending_ops_mutex);
 	assert(data->hub->pending_ops_count > 0);
Index: uspace/drv/bus/usb/usbhub/port.h
===================================================================
--- uspace/drv/bus/usb/usbhub/port.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhub/port.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -44,5 +44,5 @@
 /** Information about single port on a hub. */
 typedef struct {
-	/* Port number as reporteed in descriptors. */
+	/* Port number as reported in descriptors. */
 	size_t port_number;
 	/** Device communication pipe. */
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -170,33 +170,5 @@
 int usb_hub_device_remove(usb_device_t *usb_dev)
 {
-	assert(usb_dev);
-	usb_hub_dev_t *hub_dev = usb_dev->driver_data;
-	assert(hub_dev);
-	//TODO: Cascade the call here.
-	//TODO: Enable after cascading is implemented.
 	return ENOTSUP;
-	if (!hub_dev->power_switched) {
-		/* That is all we can do. */
-		return EOK;
-	}
-	int ret = EOK;
-	usb_log_info("Hub is about to be removed, powering down all ports.\n");
-	for (size_t port = 0; port < hub_dev->port_count; ++port) {
-		usb_log_debug("Powering down port %zu.\n", port);
-		int pret = usb_hub_port_clear_feature(
-		    &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
-		if (pret != EOK) {
-			usb_log_error("Cannot power down port %zu: %s.\n",
-			    hub_dev->ports[port].port_number, str_error(pret));
-			ret = pret;
-		} else {
-			if (!hub_dev->per_port_power) {
-				usb_log_debug("Ganged power switching mode, "
-				   "one port is enough.\n");
-				break;
-			}
-		}
-	}
-	return ret;
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/bus/usb/usbmast/bo_trans.c
===================================================================
--- uspace/drv/bus/usb/usbmast/bo_trans.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbmast/bo_trans.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -67,6 +67,6 @@
 	int retval = EOK;
 	size_t act_size;
-	usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
-	usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
+	usb_pipe_t *bulk_in_pipe = &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
+	usb_pipe_t *bulk_out_pipe = &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
 	usb_direction_t ddir;
 	void *dbuf;
@@ -118,8 +118,8 @@
 		if (ddir == USB_DIRECTION_IN) {
 			usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
-			    mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
+			    &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
 		} else {
 			usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
-			    mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
+			    &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
 		}
         } else if (rc != EOK) {
@@ -216,7 +216,7 @@
 	usb_massstor_reset(mdev);
 	usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
-	    mdev->usb_dev->pipes[BULK_IN_EP].pipe);
+	    &mdev->usb_dev->pipes[BULK_IN_EP].pipe);
 	usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
-	    mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
+	    &mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
 }
 
Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -114,4 +114,5 @@
 {
 	//TODO: flush buffers, or whatever.
+	//TODO: remove device
 	return ENOTSUP;
 }
@@ -139,10 +140,10 @@
 
 	usb_log_info("Initializing mass storage `%s'.\n", dev->ddf_dev->name);
-	usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
-	    dev->pipes[BULK_IN_EP].pipe->endpoint_no,
-	    (size_t) dev->pipes[BULK_IN_EP].descriptor->max_packet_size);
+	usb_log_debug("Bulk in endpoint: %d [%zuB].\n",
+	    dev->pipes[BULK_IN_EP].pipe.endpoint_no,
+	    dev->pipes[BULK_IN_EP].pipe.max_packet_size);
 	usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
-	    dev->pipes[BULK_OUT_EP].pipe->endpoint_no,
-	    (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
+	    dev->pipes[BULK_OUT_EP].pipe.endpoint_no,
+	    dev->pipes[BULK_OUT_EP].pipe.max_packet_size);
 
 	usb_log_debug("Get LUN count...\n");
Index: uspace/drv/bus/usb/usbmid/explore.c
===================================================================
--- uspace/drv/bus/usb/usbmid/explore.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbmid/explore.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -57,6 +57,5 @@
 {
 	list_foreach(*list, l) {
-		usbmid_interface_t *iface
-		    = list_get_instance(l, usbmid_interface_t, link);
+		usbmid_interface_t *iface = usbmid_interface_from_link(l);
 		if (iface->interface_no == interface_no) {
 			return true;
@@ -82,47 +81,43 @@
 	};
 
-	usb_dp_parser_t parser = {
+	static const usb_dp_parser_t parser = {
 		.nesting = usb_dp_standard_descriptor_nesting
 	};
 
 	const uint8_t *interface_ptr =
-	    usb_dp_get_nested_descriptor(&parser, &data, data.data);
-	if (interface_ptr == NULL) {
-		return;
-	}
-
-	do {
-		if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) {
-			goto next_descriptor;
-		}
-
-		usb_standard_interface_descriptor_t *interface
+	    usb_dp_get_nested_descriptor(&parser, &data, config_descriptor);
+
+	/* Walk all descriptors nested in the current configuration decriptor;
+	 * i.e. all interface descriptors. */
+	for (;interface_ptr != NULL;
+	    interface_ptr = usb_dp_get_sibling_descriptor(
+	        &parser, &data, config_descriptor, interface_ptr))
+	{
+		/* The second byte is DESCTYPE byte in all desriptors. */
+		if (interface_ptr[1] != USB_DESCTYPE_INTERFACE)
+			continue;
+
+		const usb_standard_interface_descriptor_t *interface
 		    = (usb_standard_interface_descriptor_t *) interface_ptr;
 
 		/* Skip alternate interfaces. */
-		if (!interface_in_list(list, interface->interface_number)) {
-			usbmid_interface_t *iface
-			    = malloc(sizeof(usbmid_interface_t));
-			if (iface == NULL) {
-				break;
-			}
-			link_initialize(&iface->link);
-			iface->fun = NULL;
-			iface->interface_no = interface->interface_number;
-			iface->interface = interface;
-
-			list_append(&iface->link, list);
-		}
-
-		/* TODO: add the alternatives and create match ids from them
-		 * as well.
-		 */
-
-next_descriptor:
-		interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data,
-		    data.data, interface_ptr);
-
-	} while (interface_ptr != NULL);
-
+		if (interface_in_list(list, interface->interface_number)) {
+			/* TODO: add the alternatives and create match ids
+			 * for them. */
+			continue;
+		}
+		usbmid_interface_t *iface = malloc(sizeof(usbmid_interface_t));
+		if (iface == NULL) {
+			//TODO: Do something about that failure.
+			break;
+		}
+
+		link_initialize(&iface->link);
+		iface->fun = NULL;
+		iface->interface_no = interface->interface_number;
+		iface->interface = interface;
+
+		list_append(&iface->link, list);
+	}
 }
 
@@ -139,14 +134,15 @@
 	int rc;
 
-	int dev_class = dev->descriptors.device.device_class;
+	unsigned dev_class = dev->descriptors.device.device_class;
 	if (dev_class != USB_CLASS_USE_INTERFACE) {
 		usb_log_warning(
-		    "Device class: %d (%s), but expected class 0.\n",
-		    dev_class, usb_str_class(dev_class));
+		    "Device class: %u (%s), but expected class %u.\n",
+		    dev_class, usb_str_class(dev_class),
+		    USB_CLASS_USE_INTERFACE);
 		usb_log_error("Not multi interface device, refusing.\n");
 		return false;
 	}
 
-	/* Short cuts to save on typing ;-). */
+	/* Shortcuts to save on typing ;-). */
 	const void *config_descriptor_raw = dev->descriptors.configuration;
 	size_t config_descriptor_size = dev->descriptors.configuration_size;
@@ -163,4 +159,5 @@
 	}
 
+	/* Create driver soft-state. */
 	usb_mid_t *usb_mid = usb_device_data_alloc(dev, sizeof(usb_mid_t));
 	if (!usb_mid) {
@@ -169,5 +166,5 @@
 	}
 
-	/* Create control function */
+	/* Create control function. */
 	usb_mid->ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
 	if (usb_mid->ctl_fun == NULL) {
@@ -175,7 +172,7 @@
 		return false;
 	}
-
 	usb_mid->ctl_fun->ops = &mid_device_ops;
 
+	/* Bind control function. */
 	rc = ddf_fun_bind(usb_mid->ctl_fun);
 	if (rc != EOK) {
@@ -192,10 +189,10 @@
 	    &usb_mid->interface_list);
 
+	/* Start child function for every interface. */
 	list_foreach(usb_mid->interface_list, link) {
-		usbmid_interface_t *iface = list_get_instance(link,
-		    usbmid_interface_t, link);
+		usbmid_interface_t *iface = usbmid_interface_from_link(link);
 
 		usb_log_info("Creating child for interface %d (%s).\n",
-		    (int) iface->interface_no,
+		    iface->interface_no,
 		    usb_str_class(iface->interface->interface_class));
 
Index: uspace/drv/bus/usb/usbmid/main.c
===================================================================
--- uspace/drv/bus/usb/usbmid/main.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbmid/main.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -68,5 +68,5 @@
 /** Callback when a MID device is about to be removed from the host.
  *
- * @param gen_dev Generic DDF device representing the removed device.
+ * @param dev USB device representing the removed device.
  * @return Error code.
  */
@@ -74,16 +74,46 @@
 {
 	assert(dev);
-	int ret = ENOTSUP;
 	usb_mid_t *usb_mid = dev->driver_data;
 	assert(usb_mid);
 
-	/* Signal all interface functions */
-	list_foreach(usb_mid->interface_list, item) {
+	/* Remove ctl function */
+	int ret = ddf_fun_unbind(usb_mid->ctl_fun);
+	if (ret != EOK) {
+		usb_log_error("Failed to unbind USB MID ctl function: %s.\n",
+		    str_error(ret));
+		return ret;
+	}
+	ddf_fun_destroy(usb_mid->ctl_fun);
+
+	/* Remove all children */
+	while (!list_empty(&usb_mid->interface_list)) {
+		link_t *item = list_first(&usb_mid->interface_list);
+		list_remove(item);
+
 		usbmid_interface_t *iface = usbmid_interface_from_link(item);
 
-		usb_log_info("Signaling remove to child for interface "
-		    "%d (%s).\n", iface->interface_no,
+		usb_log_info("Removing child for interface %d (%s).\n",
+		    iface->interface_no,
 		    usb_str_class(iface->interface->interface_class));
-		// TODO cascade the call.
+
+		/* Tell the child to go off-line. */
+		int pret = ddf_fun_offline(iface->fun);
+		if (pret != EOK) {
+			usb_log_warning("Failed to turn off child for interface"
+			    " %d (%s): %s\n", iface->interface_no,
+			    usb_str_class(iface->interface->interface_class),
+			    str_error(pret));
+			ret = pret;
+		}
+
+		/* Now remove the child. */
+		pret = usbmid_interface_destroy(iface);
+		if (pret != EOK) {
+			usb_log_error("Failed to destroy child for interface "
+			    "%d (%s): %s\n", iface->interface_no,
+			    usb_str_class(iface->interface->interface_class),
+			    str_error(pret));
+			ret = pret;
+		}
 	}
 	return ret;
@@ -92,5 +122,5 @@
 /** Callback when a MID device was removed from the host.
  *
- * @param gen_dev Generic DDF device representing the removed device.
+ * @param dev USB device representing the removed device.
  * @return Error code.
  */
@@ -98,8 +128,10 @@
 {
 	assert(dev);
+	usb_mid_t *usb_mid = dev->driver_data;
+	assert(usb_mid);
+
 	usb_log_info("USB MID gone: `%s'.\n", dev->ddf_dev->name);
 
 	/* Remove ctl function */
-	usb_mid_t *usb_mid = dev->driver_data;
 	int ret = ddf_fun_unbind(usb_mid->ctl_fun);
 	if (ret != EOK) {
@@ -117,5 +149,5 @@
 		usbmid_interface_t *iface = usbmid_interface_from_link(item);
 
-		usb_log_info("Removing child for interface %d (%s).\n",
+		usb_log_info("Child for interface %d (%s) gone.\n",
 		    iface->interface_no,
 		    usb_str_class(iface->interface->interface_class));
Index: uspace/drv/bus/usb/usbmid/usbmid.c
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbmid/usbmid.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -62,7 +62,7 @@
 /** DDF interface of the child - interface function. */
 static usb_iface_t child_usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
-	.get_address = usb_iface_get_address_hub_impl,
-	.get_interface = usb_iface_get_interface_impl
+	.get_hc_handle = usb_iface_get_hc_handle_device_impl,
+	.get_my_address = usb_iface_get_my_address_forward_impl,
+	.get_interface = usb_iface_get_interface_impl,
 };
 
@@ -110,7 +110,7 @@
 	 * class name something humanly understandable.
 	 */
-	rc = asprintf(&child_name, "%s%d",
+	rc = asprintf(&child_name, "%s%hhu",
 	    usb_str_class(interface_descriptor->interface_class),
-	    (int) interface_descriptor->interface_number);
+	    interface_descriptor->interface_number);
 	if (rc < 0) {
 		return ENOMEM;
@@ -123,9 +123,4 @@
 		return ENOMEM;
 	}
-
-	iface->fun = child;
-
-	child->driver_data = iface;
-	child->ops = &child_device_ops;
 
 	rc = usb_device_create_match_ids_from_interface(device_descriptor,
@@ -143,4 +138,8 @@
 	}
 
+	iface->fun = child;
+	child->driver_data = iface;
+	child->ops = &child_device_ops;
+
 	return EOK;
 }
Index: uspace/drv/bus/usb/usbmid/usbmid.h
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/usbmid/usbmid.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -51,5 +51,5 @@
 	ddf_fun_t *fun;
 	/** Interface descriptor. */
-	usb_standard_interface_descriptor_t *interface;
+	const usb_standard_interface_descriptor_t *interface;
 	/** Interface number. */
 	int interface_no;
Index: uspace/drv/bus/usb/vhc/connhost.c
===================================================================
--- uspace/drv/bus/usb/vhc/connhost.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/vhc/connhost.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -57,20 +57,12 @@
  * @return Error code.
  */
-static int request_address(ddf_fun_t *fun, usb_speed_t speed,
-    usb_address_t *address)
-{
-	VHC_DATA(vhc, fun);
-
-	usb_address_t addr = usb_device_manager_get_free_address(
-	    &vhc->dev_manager, USB_SPEED_HIGH);
-	if (addr < 0) {
-		return addr;
-	}
-
-	if (address != NULL) {
-		*address = addr;
-	}
-
-	return EOK;
+static int request_address(ddf_fun_t *fun, usb_address_t *address, bool strict,
+    usb_speed_t speed)
+{
+	VHC_DATA(vhc, fun);
+
+	assert(address);
+	return usb_device_manager_request_address(
+	    &vhc->dev_manager, address, strict, speed);
 }
 
@@ -88,5 +80,5 @@
 	usb_log_debug("Binding handle %" PRIun " to address %d.\n",
 	    handle, address);
-	usb_device_manager_bind(&vhc->dev_manager, address, handle);
+	usb_device_manager_bind_address(&vhc->dev_manager, address, handle);
 
 	return EOK;
@@ -118,5 +110,5 @@
 	VHC_DATA(vhc, fun);
 	usb_log_debug("Releasing address %d...\n", address);
-	usb_device_manager_release(&vhc->dev_manager, address);
+	usb_device_manager_release_address(&vhc->dev_manager, address);
 
 	return ENOTSUP;
@@ -136,5 +128,5 @@
  */
 static int register_endpoint(ddf_fun_t *fun,
-    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
+    usb_address_t address, usb_endpoint_t endpoint,
     usb_transfer_type_t transfer_type, usb_direction_t direction,
     size_t max_packet_size, unsigned int interval)
@@ -479,6 +471,5 @@
 }
 
-static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
-    usb_address_t *address)
+static int tell_address(ddf_fun_t *fun, usb_address_t *address)
 {
 	UNSUPPORTED("tell_address");
@@ -497,12 +488,9 @@
 }
 
-static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
-    usb_address_t *address)
+static int tell_address_rh(ddf_fun_t *root_hub_fun, usb_address_t *address)
 {
 	VHC_DATA(vhc, root_hub_fun);
 
-	if (handle == 0) {
-		handle = root_hub_fun->handle;
-	}
+	devman_handle_t handle = root_hub_fun->handle;
 
 	usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
@@ -532,10 +520,10 @@
 usb_iface_t vhc_usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle_hc_impl,
-	.get_address = tell_address
+	.get_my_address = tell_address
 };
 
 usb_iface_t rh_usb_iface = {
 	.get_hc_handle = usb_iface_get_hc_handle_rh_impl,
-	.get_address = tell_address_rh
+	.get_my_address = tell_address_rh
 };
 
Index: uspace/drv/bus/usb/vhc/main.c
===================================================================
--- uspace/drv/bus/usb/vhc/main.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/drv/bus/usb/vhc/main.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -80,5 +80,5 @@
 		return rc;
 	}
-	usb_device_manager_init(&data->dev_manager);
+	usb_device_manager_init(&data->dev_manager, USB_SPEED_MAX);
 
 	ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/drv/generic/remote_usb.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -40,5 +40,5 @@
 
 
-static void remote_usb_get_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usb_get_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
@@ -47,7 +47,7 @@
 /** Remote USB interface operations. */
 static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
-	remote_usb_get_address,
-	remote_usb_get_interface,
-	remote_usb_get_hc_handle
+	[IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address,
+	[IPC_M_USB_GET_INTERFACE] = remote_usb_get_interface,
+	[IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle,
 };
 
@@ -61,18 +61,16 @@
 
 
-void remote_usb_get_address(ddf_fun_t *fun, void *iface,
+void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
 {
 	usb_iface_t *usb_iface = (usb_iface_t *) iface;
 
-	if (usb_iface->get_address == NULL) {
+	if (usb_iface->get_my_address == NULL) {
 		async_answer_0(callid, ENOTSUP);
 		return;
 	}
 
-	devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
-
 	usb_address_t address;
-	int rc = usb_iface->get_address(fun, handle, &address);
+	int rc = usb_iface->get_my_address(fun, &address);
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -55,7 +55,7 @@
 static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
 	[IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,
+	[IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
 	[IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
 	[IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address,
-	[IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
 
 	[IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
@@ -118,8 +118,9 @@
 	}
 
-	usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
-
-	usb_address_t address;
-	int rc = usb_iface->request_address(fun, speed, &address);
+	usb_address_t address = DEV_IPC_GET_ARG1(*call);
+	const bool strict = DEV_IPC_GET_ARG2(*call);
+	const usb_speed_t speed = DEV_IPC_GET_ARG3(*call);
+
+	const int rc = usb_iface->request_address(fun, &address, strict, speed);
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
@@ -233,19 +234,12 @@
 
 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
-	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
+	type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16)
 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \
-	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16)
-#define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \
-	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
-#define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \
-	type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8)
-#define _INIT_FROM_LOW_DATA3(type, var, arg_no) \
-	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
+	type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff)
 
 	const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
 
-	_INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
-	_INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2);
-	_INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2);
+	_INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2);
+	_INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2);
 
 	_INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);
@@ -254,9 +248,6 @@
 #undef _INIT_FROM_HIGH_DATA2
 #undef _INIT_FROM_LOW_DATA2
-#undef _INIT_FROM_HIGH_DATA3
-#undef _INIT_FROM_MIDDLE_DATA3
-#undef _INIT_FROM_LOW_DATA3
-
-	int rc = usb_iface->register_endpoint(fun, target.address, speed,
+
+	int rc = usb_iface->register_endpoint(fun, target.address,
 	    target.endpoint, transfer_type, direction, max_packet_size, interval);
 
Index: uspace/lib/drv/include/usb_iface.h
===================================================================
--- uspace/lib/drv/include/usb_iface.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/drv/include/usb_iface.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -65,5 +65,5 @@
 	 * handle must be resolved by its parent.
 	 */
-	IPC_M_USB_GET_ADDRESS,
+	IPC_M_USB_GET_MY_ADDRESS,
 
 	/** Tell interface number given device can use.
@@ -90,5 +90,5 @@
 /** USB device communication interface. */
 typedef struct {
-	int (*get_address)(ddf_fun_t *, devman_handle_t, usb_address_t *);
+	int (*get_my_address)(ddf_fun_t *, usb_address_t *);
 	int (*get_interface)(ddf_fun_t *, devman_handle_t, int *);
 	int (*get_hc_handle)(ddf_fun_t *, devman_handle_t *);
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -170,5 +170,5 @@
 /** USB host controller communication interface. */
 typedef struct {
-	int (*request_address)(ddf_fun_t *, usb_speed_t, usb_address_t *);
+	int (*request_address)(ddf_fun_t *, usb_address_t *, bool, usb_speed_t);
 	int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t);
 	int (*find_by_address)(ddf_fun_t *, usb_address_t, devman_handle_t *);
@@ -176,5 +176,5 @@
 
 	int (*register_endpoint)(ddf_fun_t *,
-	    usb_address_t, usb_speed_t, usb_endpoint_t,
+	    usb_address_t, usb_endpoint_t,
 	    usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
 	int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usb/Makefile	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -31,4 +31,5 @@
 EXTRA_CFLAGS += \
 	-I$(LIBDRV_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
 	-Iinclude
 
Index: uspace/lib/usb/include/usb/ddfiface.h
===================================================================
--- uspace/lib/usb/include/usb/ddfiface.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usb/include/usb/ddfiface.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -39,16 +39,12 @@
 #include <usb_iface.h>
 
-int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *, devman_handle_t *);
-int usb_iface_get_address_hub_impl(ddf_fun_t *, devman_handle_t,
-    usb_address_t *);
+int usb_iface_get_hc_handle_device_impl(ddf_fun_t *, devman_handle_t *);
+int usb_iface_get_my_address_forward_impl(ddf_fun_t *, usb_address_t *);
 extern usb_iface_t usb_iface_hub_impl;
 
-int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *, devman_handle_t *);
-int usb_iface_get_address_hub_child_impl(ddf_fun_t *, devman_handle_t,
-    usb_address_t *);
+int usb_iface_get_my_address_from_device_data(ddf_fun_t *, usb_address_t *);
 extern usb_iface_t usb_iface_hub_child_impl;
 
 int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *, devman_handle_t *);
-
 
 #endif
Index: uspace/lib/usb/include/usb/hc.h
===================================================================
--- uspace/lib/usb/include/usb/hc.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usb/include/usb/hc.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -62,5 +62,5 @@
     devman_handle_t *);
 
-usb_address_t usb_hc_get_address_by_handle(devman_handle_t);
+usb_address_t usb_get_address_by_handle(devman_handle_t);
 
 int usb_hc_find(devman_handle_t, devman_handle_t *);
Index: uspace/lib/usb/src/class.c
===================================================================
--- uspace/lib/usb/src/class.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usb/src/class.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -81,5 +81,5 @@
 			return "application";
 		case USB_CLASS_VENDOR_SPECIFIC:
-			return "vendor";
+			return "vendor-specific";
 		default:
 			return "unknown";
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usb/src/ddfiface.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -39,17 +39,18 @@
 #include <usb/hc.h>
 #include <usb/debug.h>
+#include <usb/dev/hub.h>
 #include <errno.h>
 #include <assert.h>
 
 /** DDF interface for USB device, implementation for typical hub. */
-usb_iface_t  usb_iface_hub_impl = {
-	.get_hc_handle = usb_iface_get_hc_handle_hub_impl,
-	.get_address = usb_iface_get_address_hub_impl
+usb_iface_t usb_iface_hub_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_device_impl,
+	.get_my_address = usb_iface_get_my_address_forward_impl,
 };
 
 /** DDF interface for USB device, implementation for child of a typical hub. */
-usb_iface_t  usb_iface_hub_child_impl = {
-	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
-	.get_address = usb_iface_get_address_hub_child_impl
+usb_iface_t usb_iface_hub_child_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_device_impl,
+	.get_my_address = usb_iface_get_my_address_from_device_data,
 };
 
@@ -61,42 +62,8 @@
  * @return Error code.
  */
-int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *fun, devman_handle_t *handle)
+int usb_iface_get_hc_handle_device_impl(ddf_fun_t *fun, devman_handle_t *handle)
 {
 	assert(fun);
 	return usb_hc_find(fun->handle, handle);
-}
-
-/** Get host controller handle, interface implementation for child of
- * a hub driver.
- *
- * @param[in] fun Device function the operation is running on.
- * @param[out] handle Storage for the host controller handle.
- * @return Error code.
- */
-int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *fun,
-    devman_handle_t *handle)
-{
-	assert(fun != NULL);
-	
-	async_sess_t *parent_sess =
-	    devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle,
-	    IPC_FLAG_BLOCKING);
-	if (!parent_sess)
-		return ENOMEM;
-	
-	async_exch_t *exch = async_exchange_begin(parent_sess);
-	
-	sysarg_t hc_handle;
-	int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &hc_handle);
-	
-	async_exchange_end(exch);
-	async_hangup(parent_sess);
-	
-	if (rc != EOK)
-		return rc;
-	
-	*handle = hc_handle;
-	return EOK;
 }
 
@@ -125,9 +92,9 @@
  * @return Error code.
  */
-int usb_iface_get_address_hub_impl(ddf_fun_t *fun, devman_handle_t handle,
+int usb_iface_get_my_address_forward_impl(ddf_fun_t *fun,
     usb_address_t *address)
 {
 	assert(fun);
-	
+
 	async_sess_t *parent_sess =
 	    devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle,
@@ -135,20 +102,20 @@
 	if (!parent_sess)
 		return ENOMEM;
-	
+
 	async_exch_t *exch = async_exchange_begin(parent_sess);
-	
+
 	sysarg_t addr;
-	int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_ADDRESS, handle, &addr);
-	
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_MY_ADDRESS, &addr);
+
 	async_exchange_end(exch);
 	async_hangup(parent_sess);
-	
+
 	if (rc != EOK)
 		return rc;
-	
+
 	if (address != NULL)
 		*address = (usb_address_t) addr;
-	
+
 	return EOK;
 }
@@ -157,4 +124,7 @@
  * a hub driver.
  *
+ * This implementation eccepts 0 as valid handle and replaces it with fun's
+ * handle.
+ *
  * @param[in] fun Device function the operation is running on.
  * @param[in] handle Devman handle of USB device we want address of.
@@ -162,11 +132,14 @@
  * @return Error code.
  */
-int usb_iface_get_address_hub_child_impl(ddf_fun_t *fun,
-    devman_handle_t handle, usb_address_t *address)
+int usb_iface_get_my_address_from_device_data(ddf_fun_t *fun,
+    usb_address_t *address)
 {
-	if (handle == 0) {
-		handle = fun->handle;
-	}
-	return usb_iface_get_address_hub_impl(fun, handle, address);
+	assert(fun);
+	assert(fun->driver_data);
+	usb_hub_attached_device_t *device = fun->driver_data;
+	assert(device->fun == fun);
+	if (address)
+		*address = device->address;
+	return EOK;
 }
 
Index: uspace/lib/usb/src/hc.c
===================================================================
--- uspace/lib/usb/src/hc.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usb/src/hc.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -174,5 +174,5 @@
  * @return USB address or negative error code.
  */
-usb_address_t usb_hc_get_address_by_handle(devman_handle_t dev_handle)
+usb_address_t usb_get_address_by_handle(devman_handle_t dev_handle)
 {
 	async_sess_t *parent_sess =
@@ -185,7 +185,6 @@
 	
 	sysarg_t address;
-	int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_ADDRESS,
-	    dev_handle, &address);
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_MY_ADDRESS, &address);
 	
 	async_exchange_end(exch);
Index: uspace/lib/usb/src/resolve.c
===================================================================
--- uspace/lib/usb/src/resolve.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usb/src/resolve.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -200,5 +200,5 @@
 		/* Try to get its address. */
 		if (!found_addr) {
-			dev_addr = usb_hc_get_address_by_handle(tmp_handle);
+			dev_addr = usb_get_address_by_handle(tmp_handle);
 			if (dev_addr >= 0) {
 				found_addr = true;
Index: uspace/lib/usbdev/include/usb/dev/dp.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/dp.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/include/usb/dev/dp.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -54,5 +54,5 @@
 } usb_dp_descriptor_nesting_t;
 
-extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
+extern const usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
 
 /** Descriptor parser structure. */
Index: uspace/lib/usbdev/include/usb/dev/driver.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/driver.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/include/usb/dev/driver.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -72,4 +72,8 @@
 /** USB device structure. */
 typedef struct {
+	/** Connection backing the pipes.
+	 * Typically, you will not need to use this attribute at all.
+	 */
+	usb_device_connection_t wire;
 	/** The default control pipe. */
 	usb_pipe_t ctrl_pipe;
@@ -87,14 +91,11 @@
 	int interface_no;
 
-	/** Alternative interfaces.
-	 * Set to NULL when the driver controls whole device
-	 * (i.e. more (or any) interfaces).
-	 */
-	usb_alternate_interfaces_t *alternate_interfaces;
+	/** Alternative interfaces. */
+	usb_alternate_interfaces_t alternate_interfaces;
 
 	/** Some useful descriptors. */
 	usb_device_descriptors_t descriptors;
 
-	/** Generic DDF device backing this one. RO: DO NOT TOUCH!*/
+	/** Generic DDF device backing this one. DO NOT TOUCH! */
 	ddf_dev_t *ddf_dev;
 	/** Custom driver data.
@@ -103,9 +104,4 @@
 	 */
 	void *driver_data;
-
-	/** Connection backing the pipes.
-	 * Typically, you will not need to use this attribute at all.
-	 */
-	usb_device_connection_t wire;
 } usb_device_t;
 
@@ -163,22 +159,25 @@
 int usb_driver_main(const usb_driver_t *);
 
+int usb_device_init(usb_device_t *, ddf_dev_t *,
+    const usb_endpoint_description_t **, const char **);
+void usb_device_deinit(usb_device_t *);
+
 int usb_device_select_interface(usb_device_t *, uint8_t,
     const usb_endpoint_description_t **);
 
 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
+void usb_device_release_descriptors(usb_device_descriptors_t *);
+
 int usb_device_create_pipes(const ddf_dev_t *, usb_device_connection_t *,
     const usb_endpoint_description_t **, const uint8_t *, size_t, int, int,
     usb_endpoint_mapping_t **, size_t *);
 int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
-int usb_device_init(usb_device_t *, ddf_dev_t *,
-    const usb_endpoint_description_t **, const char **);
-void usb_device_deinit(usb_device_t *);
 
 void * usb_device_data_alloc(usb_device_t *, size_t);
 
 size_t usb_interface_count_alternates(const uint8_t *, size_t, uint8_t);
-int usb_alternate_interfaces_create(const uint8_t *, size_t, int,
-    usb_alternate_interfaces_t **);
-void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *);
+int usb_alternate_interfaces_init(usb_alternate_interfaces_t *,
+    const uint8_t *, size_t, int);
+void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *);
 #endif
 /**
Index: uspace/lib/usbdev/include/usb/dev/hub.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/hub.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/include/usb/dev/hub.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -59,5 +59,6 @@
 } usb_hub_attached_device_t;
 
-usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
+usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t,
+    bool, usb_speed_t);
 int usb_hc_register_device(usb_hc_connection_t *,
     const usb_hub_attached_device_t *);
Index: uspace/lib/usbdev/include/usb/dev/pipes.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/pipes.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/include/usb/dev/pipes.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -141,5 +141,5 @@
 typedef struct {
 	/** Endpoint pipe. */
-	usb_pipe_t *pipe;
+	usb_pipe_t pipe;
 	/** Endpoint description. */
 	const usb_endpoint_description_t *description;
@@ -149,7 +149,7 @@
 	int interface_setting;
 	/** Found descriptor fitting the description. */
-	usb_standard_endpoint_descriptor_t *descriptor;
+	const usb_standard_endpoint_descriptor_t *descriptor;
 	/** Interface descriptor the endpoint belongs to. */
-	usb_standard_interface_descriptor_t *interface;
+	const usb_standard_interface_descriptor_t *interface;
 	/** Whether the endpoint was actually found. */
 	bool present;
@@ -172,6 +172,4 @@
 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
     size_t, const uint8_t *, size_t, usb_device_connection_t *);
-int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t,
-    unsigned int, usb_hc_connection_t *);
 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
 int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
Index: uspace/lib/usbdev/include/usb/dev/poll.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/poll.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/include/usb/dev/poll.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -84,6 +84,6 @@
 } usb_device_auto_polling_t;
 
-int usb_device_auto_polling(usb_device_t *, size_t, usb_device_auto_polling_t *,
-    size_t, void *);
+int usb_device_auto_polling(usb_device_t *, size_t,
+    const usb_device_auto_polling_t *, size_t, void *);
 
 typedef bool (*usb_polling_callback_t)(usb_device_t *,
Index: uspace/lib/usbdev/include/usb/dev/recognise.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/recognise.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/include/usb/dev/recognise.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -50,5 +50,5 @@
 int usb_device_create_match_ids(usb_pipe_t *, match_id_list_t *);
 
-int usb_device_register_child_in_devman(usb_address_t, devman_handle_t,
+int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
     ddf_dev_t *, ddf_dev_ops_t *, void *, ddf_fun_t **);
 
Index: uspace/lib/usbdev/include/usb/dev/request.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/request.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/include/usb/dev/request.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -115,7 +115,6 @@
 int usb_request_set_feature(usb_pipe_t *, usb_request_type_t,
     usb_request_recipient_t, uint16_t, uint16_t);
-int usb_request_set_address(usb_pipe_t *, usb_address_t);
 int usb_request_get_descriptor(usb_pipe_t *, usb_request_type_t,
-    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t, 
+    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t,
     size_t *);
 int usb_request_get_descriptor_alloc(usb_pipe_t *, usb_request_type_t,
@@ -131,4 +130,5 @@
 int usb_request_set_descriptor(usb_pipe_t *, usb_request_type_t,
     usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t);
+
 int usb_request_get_configuration(usb_pipe_t *, uint8_t *);
 int usb_request_set_configuration(usb_pipe_t *, uint8_t);
Index: uspace/lib/usbdev/src/altiface.c
===================================================================
--- uspace/lib/usbdev/src/altiface.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/altiface.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -90,21 +90,17 @@
  * @return Error code.
  */
-int usb_alternate_interfaces_create(const uint8_t *config_descr,
-    size_t config_descr_size, int interface_number,
-    usb_alternate_interfaces_t **alternates_ptr)
+int usb_alternate_interfaces_init(usb_alternate_interfaces_t *alternates,
+    const uint8_t *config_descr, size_t config_descr_size, int interface_number)
 {
-	assert(alternates_ptr != NULL);
+	assert(alternates != NULL);
 	assert(config_descr != NULL);
 	assert(config_descr_size > 0);
 
-	*alternates_ptr = NULL;
+	alternates->alternatives = NULL;
+	alternates->alternative_count = 0;
+	alternates->current = 0;
+
 	if (interface_number < 0) {
 		return EOK;
-	}
-
-	usb_alternate_interfaces_t *alternates
-	    = malloc(sizeof(usb_alternate_interfaces_t));
-	if (alternates == NULL) {
-		return ENOMEM;
 	}
 
@@ -114,5 +110,4 @@
 
 	if (alternates->alternative_count == 0) {
-		free(alternates);
 		return ENOENT;
 	}
@@ -121,14 +116,11 @@
 	    sizeof(usb_alternate_interface_descriptors_t));
 	if (alternates->alternatives == NULL) {
-		free(alternates);
 		return ENOMEM;
 	}
 
-	alternates->current = 0;
-
-	usb_dp_parser_t dp_parser = {
+	const usb_dp_parser_t dp_parser = {
 		.nesting = usb_dp_standard_descriptor_nesting
 	};
-	usb_dp_parser_data_t dp_data = {
+	const usb_dp_parser_data_t dp_data = {
 		.data = config_descr,
 		.size = config_descr_size,
@@ -147,6 +139,5 @@
 		    || (iface->interface_number != interface_number)) {
 			iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
-			    &dp_data,
-			    dp_data.data, iface_ptr);
+			    &dp_data, dp_data.data, iface_ptr);
 			continue;
 		}
@@ -170,15 +161,12 @@
 	}
 
-	*alternates_ptr = alternates;
-
 	return EOK;
 }
 
-void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *alternate)
+void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *alternate)
 {
 	if (!alternate)
 		return;
 	free(alternate->alternatives);
-	free(alternate);
 }
 /**
Index: uspace/lib/usbdev/src/devdrv.c
===================================================================
--- uspace/lib/usbdev/src/devdrv.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/devdrv.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -81,15 +81,9 @@
  * @return Number of pipes (excluding default control pipe).
  */
-static size_t count_other_pipes(const usb_endpoint_description_t **endpoints)
-{
-	size_t count = 0;
-	if (endpoints == NULL) {
-		return 0;
-	}
-
-	while (endpoints[count] != NULL) {
-		count++;
-	}
-
+static inline size_t count_other_pipes(
+    const usb_endpoint_description_t **endpoints)
+{
+	size_t count;
+	for (count = 0; endpoints && endpoints[count] != NULL; ++count);
 	return count;
 }
@@ -104,4 +98,6 @@
     usb_device_t *dev, int alternate_setting)
 {
+	assert(dev);
+
 	if (endpoints == NULL) {
 		dev->pipes = NULL;
@@ -300,4 +296,15 @@
 
 	return rc;
+}
+
+/** Cleanup structure initialized via usb_device_retrieve_descriptors.
+ *
+ * @param[in] descriptors Where to store the descriptors.
+ */
+void usb_device_release_descriptors(usb_device_descriptors_t *descriptors)
+{
+	assert(descriptors);
+	free(descriptors->configuration);
+	descriptors->configuration = NULL;
 }
 
@@ -319,5 +326,5 @@
  *	(not NULL terminated).
  * @param[out] pipes_count_ptr Where to store number of pipes
- *	(set to if you wish to ignore the count).
+ *	(set to NULL if you wish to ignore the count).
  * @return Error code.
  */
@@ -340,5 +347,6 @@
 	const size_t pipe_count = count_other_pipes(endpoints);
 	if (pipe_count == 0) {
-		*pipes_count_ptr = pipe_count;
+		if (pipes_count_ptr)
+			*pipes_count_ptr = pipe_count;
 		*pipes_ptr = NULL;
 		return EOK;
@@ -346,21 +354,11 @@
 
 	usb_endpoint_mapping_t *pipes
-	    = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
+	    = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
 	if (pipes == NULL) {
 		return ENOMEM;
 	}
 
-	/* Initialize to NULL to allow smooth rollback. */
-	for (i = 0; i < pipe_count; i++) {
-		pipes[i].pipe = NULL;
-	}
-
 	/* Now allocate and fully initialize. */
 	for (i = 0; i < pipe_count; i++) {
-		pipes[i].pipe = malloc(sizeof(usb_pipe_t));
-		if (pipes[i].pipe == NULL) {
-			rc = ENOMEM;
-			goto rollback_free_only;
-		}
 		pipes[i].description = endpoints[i];
 		pipes[i].interface_no = interface_no;
@@ -389,5 +387,5 @@
 	for (i = 0; i < pipe_count; i++) {
 		if (pipes[i].present) {
-			rc = usb_pipe_register(pipes[i].pipe,
+			rc = usb_pipe_register(&pipes[i].pipe,
 			    pipes[i].descriptor->poll_interval, &hc_conn);
 			if (rc != EOK) {
@@ -398,6 +396,6 @@
 
 	if (usb_hc_connection_close(&hc_conn) != EOK)
-		usb_log_warning("usb_device_create_pipes(): "
-		    "Failed to close connection.\n");
+		usb_log_warning("%s: Failed to close connection.\n",
+		    __FUNCTION__);
 
 	*pipes_ptr = pipes;
@@ -417,5 +415,5 @@
 	for (i = 0; i < pipe_count; i++) {
 		if (pipes[i].present) {
-			usb_pipe_unregister(pipes[i].pipe, &hc_conn);
+			usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
 		}
 	}
@@ -431,9 +429,4 @@
 	 */
 rollback_free_only:
-	for (i = 0; i < pipe_count; i++) {
-		if (pipes[i].pipe != NULL) {
-			free(pipes[i].pipe);
-		}
-	}
 	free(pipes);
 
@@ -477,6 +470,5 @@
 		    i, pipes[i].present ? "" : "not ");
 		if (pipes[i].present)
-			usb_pipe_unregister(pipes[i].pipe, &hc_conn);
-		free(pipes[i].pipe);
+			usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
 	}
 
@@ -489,32 +481,4 @@
 	return EOK;
 }
-
-/** Initialize control pipe in a device.
- *
- * @param dev USB device in question.
- * @param errmsg Where to store error context.
- * @return
- */
-static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
-{
-	int rc;
-
-	rc = usb_device_connection_initialize_from_device(&dev->wire,
-	    dev->ddf_dev);
-	if (rc != EOK) {
-		*errmsg = "device connection initialization";
-		return rc;
-	}
-
-	rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
-	    &dev->wire);
-	if (rc != EOK) {
-		*errmsg = "default control pipe initialization";
-		return rc;
-	}
-
-	return EOK;
-}
-
 
 /** Initialize new instance of USB device.
@@ -533,14 +497,26 @@
 	assert(ddf_dev != NULL);
 
+	*errstr_ptr = NULL;
+
 	usb_dev->ddf_dev = ddf_dev;
 	usb_dev->driver_data = NULL;
 	usb_dev->descriptors.configuration = NULL;
-	usb_dev->alternate_interfaces = NULL;
 	usb_dev->pipes_count = 0;
 	usb_dev->pipes = NULL;
 
 	/* Initialize backing wire and control pipe. */
-	int rc = init_wire_and_ctrl_pipe(usb_dev, errstr_ptr);
-	if (rc != EOK) {
+	int rc = usb_device_connection_initialize_from_device(
+	    &usb_dev->wire, ddf_dev);
+	if (rc != EOK) {
+		*errstr_ptr = "device connection initialization";
+		return rc;
+	}
+
+	/* This pipe was registered by the hub driver,
+	 * during device initialization. */
+	rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe,
+	    &usb_dev->wire);
+	if (rc != EOK) {
+		*errstr_ptr = "default control pipe initialization";
 		return rc;
 	}
@@ -553,26 +529,28 @@
 	    &usb_dev->descriptors);
 	if (rc != EOK) {
-		/* Nothing allocated, nothing to free. */
 		*errstr_ptr = "descriptor retrieval";
 		return rc;
 	}
 
-	/* Create alternate interfaces. We will silently ignore failure. */
-	//TODO Why ignore?
-	usb_alternate_interfaces_create(usb_dev->descriptors.configuration,
-	    usb_dev->descriptors.configuration_size, usb_dev->interface_no,
-	    &usb_dev->alternate_interfaces);
-
-	rc = initialize_other_pipes(endpoints, usb_dev, 0);
+	/* Create alternate interfaces. We will silently ignore failure.
+	 * We might either control one interface or an entire device,
+	 * it makes no sense to speak about alternate interfaces when
+	 * controlling a device. */
+	rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
+	    usb_dev->descriptors.configuration,
+	    usb_dev->descriptors.configuration_size, usb_dev->interface_no);
+	const int alternate_iface =
+	    (rc == EOK) ? usb_dev->alternate_interfaces.current : 0;
+
+	/* TODO Add comment here. */
+	rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface);
 	if (rc != EOK) {
 		/* Full configuration descriptor is allocated. */
-		free(usb_dev->descriptors.configuration);
+		usb_device_release_descriptors(&usb_dev->descriptors);
 		/* Alternate interfaces may be allocated */
-		usb_alternate_interfaces_destroy(usb_dev->alternate_interfaces);
+		usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces);
 		*errstr_ptr = "pipes initialization";
 		return rc;
 	}
-
-	*errstr_ptr = NULL;
 
 	return EOK;
@@ -591,6 +569,6 @@
 		destroy_current_pipes(dev);
 
-		usb_alternate_interfaces_destroy(dev->alternate_interfaces);
-		free(dev->descriptors.configuration);
+		usb_alternate_interfaces_deinit(&dev->alternate_interfaces);
+		usb_device_release_descriptors(&dev->descriptors);
 		free(dev->driver_data);
 	}
Index: uspace/lib/usbdev/src/devpoll.c
===================================================================
--- uspace/lib/usbdev/src/devpoll.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/devpoll.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -73,5 +73,5 @@
 
 	usb_pipe_t *pipe
-	    = polling_data->dev->pipes[polling_data->pipe_index].pipe;
+	    = &polling_data->dev->pipes[polling_data->pipe_index].pipe;
 	
 	if (polling_data->debug > 0) {
@@ -208,29 +208,21 @@
 		return EINVAL;
 	}
-	if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
-	    || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
+	if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
+	    || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
 		return EINVAL;
 	}
 
-	usb_device_auto_polling_t *auto_polling
-	    = malloc(sizeof(usb_device_auto_polling_t));
-	if (auto_polling == NULL) {
-		return ENOMEM;
-	}
-
-	auto_polling->debug = 1;
-	auto_polling->auto_clear_halt = true;
-	auto_polling->delay = 0;
-	auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
-	auto_polling->on_data = callback;
-	auto_polling->on_polling_end = terminated_callback;
-	auto_polling->on_error = NULL;
-
-	int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
+	const usb_device_auto_polling_t auto_polling = {
+		.debug = 1,
+		.auto_clear_halt = true,
+		.delay = 0,
+		.max_failures = MAX_FAILED_ATTEMPTS,
+		.on_data = callback,
+		.on_polling_end = terminated_callback,
+		.on_error = NULL,
+	};
+
+	return usb_device_auto_polling(dev, pipe_index, &auto_polling,
 	   request_size, arg);
-
-	free(auto_polling);
-
-	return rc;
 }
 
@@ -253,5 +245,5 @@
  */
 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
-    usb_device_auto_polling_t *polling,
+    const usb_device_auto_polling_t *polling,
     size_t request_size, void *arg)
 {
@@ -262,6 +254,6 @@
 		return EINVAL;
 	}
-	if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
-	    || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
+	if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
+	    || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
 		return EINVAL;
 	}
Index: uspace/lib/usbdev/src/dp.c
===================================================================
--- uspace/lib/usbdev/src/dp.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/dp.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -57,5 +57,5 @@
 
 /** Nesting of standard USB descriptors. */
-usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
+const usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
 	NESTING(CONFIGURATION, INTERFACE),
 	NESTING(INTERFACE, ENDPOINT),
Index: uspace/lib/usbdev/src/hub.c
===================================================================
--- uspace/lib/usbdev/src/hub.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/hub.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -66,4 +66,6 @@
  *
  * @param connection Opened connection to host controller.
+ * @param preferred Preferred SUB address.
+ * @param strict Fail if the preferred address is not avialable.
  * @param speed Speed of the new device (device that will be assigned
  *    the returned address).
@@ -71,5 +73,5 @@
  */
 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
-    usb_speed_t speed)
+    usb_address_t preferred, bool strict, usb_speed_t speed)
 {
 	CHECK_CONNECTION(connection);
@@ -78,7 +80,6 @@
 	
 	sysarg_t address;
-	int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_REQUEST_ADDRESS, speed,
-	    &address);
+	int rc = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_REQUEST_ADDRESS, preferred, strict, speed, &address);
 	
 	async_exchange_end(exch);
@@ -132,22 +133,50 @@
 }
 
-
-static void unregister_control_endpoint_on_default_address(
-    usb_hc_connection_t *connection)
+/** Change address of connected device.
+ * This function automatically updates the backing connection to point to
+ * the new address. It also unregisterrs the old endpoint and registers
+ * a new one.
+ * This creates whole bunch of problems:
+ *  1. All pipes using this wire are broken because they are not
+ *     registered for new address
+ *  2. All other pipes for this device are using wrong address,
+ *     possibly targeting completely different device
+ *
+ * @param pipe Control endpoint pipe (session must be already started).
+ * @param new_address New USB address to be set (in native endianness).
+ * @return Error code.
+ */
+static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address,
+    usb_hc_connection_t *hc_conn)
 {
-	usb_device_connection_t dev_conn;
-	int rc = usb_device_connection_initialize_on_default_address(&dev_conn,
-	    connection);
-	if (rc != EOK) {
-		return;
-	}
-
-	usb_pipe_t ctrl_pipe;
-	rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
-	if (rc != EOK) {
-		return;
-	}
-
-	usb_pipe_unregister(&ctrl_pipe, connection);
+	if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
+		return EINVAL;
+	}
+	assert(pipe);
+	assert(hc_conn);
+	assert(pipe->wire != NULL);
+
+	const uint16_t addr = uint16_host2usb((uint16_t)new_address);
+
+	int rc = usb_control_request_set(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_ADDRESS, addr, 0, NULL, 0);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* TODO: prevent others from accessing the wire now. */
+	if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
+		usb_log_warning(
+		    "Failed to unregister the old pipe on address change.\n");
+	}
+	/* The address is already changed so set it in the wire */
+	pipe->wire->address = new_address;
+	rc = usb_pipe_register(pipe, 0, hc_conn);
+	if (rc != EOK)
+		return EADDRNOTAVAIL;
+
+	return EOK;
 }
 
@@ -171,5 +200,5 @@
  *
  * @param[in] parent Parent device (i.e. the hub device).
- * @param[in] connection Connection to host controller.
+ * @param[in] connection Connection to host controller. Must be non-null.
  * @param[in] dev_speed New device speed.
  * @param[in] enable_port Function for enabling signaling through the port the
@@ -177,10 +206,12 @@
  * @param[in] arg Any data argument to @p enable_port.
  * @param[out] assigned_address USB address of the device.
- * @param[in] dev_ops Child device ops.
+ * @param[in] dev_ops Child device ops. Will use default if not provided.
  * @param[in] new_dev_data Arbitrary pointer to be stored in the child
- *	as @c driver_data.
+ *	as @c driver_data. Will allocate and assign usb_hub_attached_device_t
+ *	structure if NULL.
  * @param[out] new_fun Storage where pointer to allocated child function
- *	will be written.
+ *	will be written. Must be non-null.
  * @return Error code.
+ * @retval EINVAL Either connection or new_fun is a NULL pointer.
  * @retval ENOENT Connection to HC not opened.
  * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
@@ -195,6 +226,9 @@
     ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
 {
-	assert(connection != NULL);
+	if (new_fun == NULL || connection == NULL)
+		return EINVAL;
+
 	// FIXME: this is awful, we are accessing directly the structure.
+	// TODO: Why not use provided connection?
 	usb_hc_connection_t hc_conn = {
 		.hc_handle = connection->hc_handle,
@@ -215,9 +249,9 @@
 	}
 
-
 	/*
 	 * Request new address.
 	 */
-	usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);
+	usb_address_t dev_addr =
+	    usb_hc_request_address(&hc_conn, 0, false, dev_speed);
 	if (dev_addr < 0) {
 		rc = EADDRNOTAVAIL;
@@ -240,6 +274,5 @@
 
 	usb_pipe_t ctrl_pipe;
-	rc = usb_pipe_initialize_default_control(&ctrl_pipe,
-	    &dev_conn);
+	rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
 	if (rc != EOK) {
 		rc = ENOTCONN;
@@ -248,11 +281,22 @@
 
 	do {
-		rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
-		    &hc_conn);
-		if (rc != EOK) {
+		rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT,
+		    true, dev_speed);
+		if (rc == ENOENT) {
 			/* Do not overheat the CPU ;-). */
 			async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
 		}
-	} while (rc != EOK);
+	} while (rc == ENOENT);
+	if (rc < 0) {
+		goto leave_release_free_address;
+	}
+
+	/* Register control pipe on default address. */
+	rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
 	struct timeval end_time;
 
@@ -267,13 +311,10 @@
 	 * above might use much of this time so we should only wait to fill
 	 * up the 100ms quota*/
-	suseconds_t elapsed = tv_sub(&end_time, &start_time);
+	const suseconds_t elapsed = tv_sub(&end_time, &start_time);
 	if (elapsed < 100000) {
 		async_usleep(100000 - elapsed);
 	}
 
-	/*
-	 * Endpoint is registered. We can enable the port and change
-	 * device address.
-	 */
+	/* Endpoint is registered. We can enable the port and change address. */
 	rc = enable_port(arg);
 	if (rc != EOK) {
@@ -287,4 +328,5 @@
 	async_usleep(10000);
 
+	/* Get max_packet_size value. */
 	rc = usb_pipe_probe_default_control(&ctrl_pipe);
 	if (rc != EOK) {
@@ -293,5 +335,5 @@
 	}
 
-	rc = usb_request_set_address(&ctrl_pipe, dev_addr);
+	rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn);
 	if (rc != EOK) {
 		rc = ESTALL;
@@ -299,53 +341,40 @@
 	}
 
-	/*
-	 * Address changed. We can release the original endpoint, thus
-	 * allowing other to access the default address.
-	 */
-	unregister_control_endpoint_on_default_address(&hc_conn);
-
-	/*
-	 * Time to register the new endpoint.
-	 */
-	rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
-	if (rc != EOK) {
-		goto leave_release_free_address;
-	}
-
-	/*
-	 * It is time to register the device with devman.
-	 */
+	/* Address changed. We can release the default, thus
+	 * allowing other to access the default address. */
+	usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
+
+	/* Register the device with devman. */
 	/* FIXME: create device_register that will get opened ctrl pipe. */
 	ddf_fun_t *child_fun;
-	rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
+	rc = usb_device_register_child_in_devman(&ctrl_pipe,
 	    parent, dev_ops, new_dev_data, &child_fun);
 	if (rc != EOK) {
-		rc = ESTALL;
 		goto leave_release_free_address;
 	}
 
-	/*
-	 * And now inform the host controller about the handle.
-	 */
-	usb_hub_attached_device_t new_device = {
+	const usb_hub_attached_device_t new_device = {
 		.address = dev_addr,
 		.fun = child_fun,
 	};
+
+
+	/* Inform the host controller about the handle. */
 	rc = usb_hc_register_device(&hc_conn, &new_device);
 	if (rc != EOK) {
+		/* We know nothing about that data. */
+		if (new_dev_data)
+			child_fun->driver_data = NULL;
+		/* The child function is already created. */
+		ddf_fun_destroy(child_fun);
 		rc = EDESTADDRREQ;
 		goto leave_release_free_address;
 	}
 
-
-	/*
-	 * And we are done.
-	 */
 	if (assigned_address != NULL) {
 		*assigned_address = dev_addr;
 	}
-	if (new_fun != NULL) {
-		*new_fun = child_fun;
-	}
+
+	*new_fun = child_fun;
 
 	rc = EOK;
@@ -357,13 +386,20 @@
 	 */
 leave_release_default_address:
-	usb_pipe_unregister(&ctrl_pipe, &hc_conn);
+	usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
 
 leave_release_free_address:
-	usb_hc_unregister_device(&hc_conn, dev_addr);
+	/* This might be either 0:0 or dev_addr:0 */
+	if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
+		usb_log_warning("%s: Failed to unregister default pipe.\n",
+		    __FUNCTION__);
+
+	if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK)
+		usb_log_warning("%s: Failed to unregister device.\n",
+		    __FUNCTION__);
 
 close_connection:
 	if (usb_hc_connection_close(&hc_conn) != EOK)
-		usb_log_warning("usb_hc_new_device_wrapper(): Failed to close "
-		    "connection.\n");
+		usb_log_warning("%s: Failed to close hc connection.\n",
+		    __FUNCTION__);
 
 	return rc;
Index: uspace/lib/usbdev/src/pipes.c
===================================================================
--- uspace/lib/usbdev/src/pipes.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/pipes.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -56,12 +56,7 @@
 	async_exch_t *exch = async_exchange_begin(sess);
 	
-	/*
-	 * We are sending special value as a handle - zero - to get
-	 * handle of the parent function (that handle was used
-	 * when registering our device @p dev.
-	 */
 	sysarg_t address;
-	int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_ADDRESS, 0, &address);
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_MY_ADDRESS, &address);
 	
 	async_exchange_end(exch);
@@ -80,4 +75,5 @@
 int usb_device_get_assigned_interface(const ddf_dev_t *device)
 {
+	assert(device);
 	async_sess_t *parent_sess =
 	    devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle,
Index: uspace/lib/usbdev/src/pipesinit.c
===================================================================
--- uspace/lib/usbdev/src/pipesinit.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/pipesinit.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -192,12 +192,9 @@
 	}
 
-	if (ep_mapping->pipe == NULL) {
-		return EBADMEM;
-	}
 	if (ep_mapping->present) {
 		return EEXISTS;
 	}
 
-	int rc = usb_pipe_initialize(ep_mapping->pipe, wire,
+	int rc = usb_pipe_initialize(&ep_mapping->pipe, wire,
 	    ep_no, description.transfer_type, endpoint->max_packet_size,
 	    description.direction);
@@ -254,5 +251,5 @@
  *
  * The mapping array is expected to conform to following rules:
- * - @c pipe must point to already allocated structure with uninitialized pipe
+ * - @c pipe must be uninitialized pipe
  * - @c description must point to prepared endpoint description
  * - @c descriptor does not need to be initialized (will be overwritten)
@@ -297,9 +294,6 @@
 	}
 
-	/*
-	 * Go through the mapping and set all endpoints to not present.
-	 */
-	size_t i;
-	for (i = 0; i < mapping_count; i++) {
+	/* Go through the mapping and set all endpoints to not present. */
+	for (size_t i = 0; i < mapping_count; i++) {
 		mapping[i].present = false;
 		mapping[i].descriptor = NULL;
@@ -307,7 +301,5 @@
 	}
 
-	/*
-	 * Prepare the descriptor parser.
-	 */
+	/* Prepare the descriptor parser. */
 	const usb_dp_parser_t dp_parser = {
 		.nesting = descriptor_nesting
@@ -454,50 +446,25 @@
  * @return Error code.
  */
-int usb_pipe_register(usb_pipe_t *pipe,
-    unsigned int interval,
-    usb_hc_connection_t *hc_connection)
-{
-	return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,
-	    interval, hc_connection);
-}
-
-/** Register endpoint with a speed at the host controller.
- *
- * You will rarely need to use this function because it is needed only
- * if the registered endpoint is of address 0 and there is no other way
- * to tell speed of the device at address 0.
- *
- * @param pipe Pipe to be registered.
- * @param speed Speed of the device
- *	(invalid speed means use previously specified one).
- * @param interval Polling interval.
- * @param hc_connection Connection to the host controller (must be opened).
- * @return Error code.
- */
-int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,
-    unsigned int interval,
+int usb_pipe_register(usb_pipe_t *pipe, unsigned interval,
     usb_hc_connection_t *hc_connection)
 {
 	assert(pipe);
 	assert(hc_connection);
-	
+
 	if (!usb_hc_connection_is_opened(hc_connection))
 		return EBADF;
-	
+
 	const usb_target_t target =
 	    {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
-#define _PACK2(high, low) (((high) << 16) + (low))
-#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
-	
+#define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))
+
 	async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
 	int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
 	    IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
-	    _PACK3(speed, pipe->transfer_type, pipe->direction),
+	    _PACK2(pipe->transfer_type, pipe->direction),
 	    _PACK2(pipe->max_packet_size, interval));
 	async_exchange_end(exch);
-	
+
 #undef _PACK2
-#undef _PACK3
-	
 	return rc;
 }
Index: uspace/lib/usbdev/src/recognise.c
===================================================================
--- uspace/lib/usbdev/src/recognise.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/recognise.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -35,4 +35,6 @@
 #include <sys/types.h>
 #include <fibril_synch.h>
+#include <usb/debug.h>
+#include <usb/dev/hub.h>
 #include <usb/dev/pipes.h>
 #include <usb/dev/recognise.h>
@@ -50,5 +52,5 @@
 
 /** DDF operations of child devices. */
-ddf_dev_ops_t child_ops = {
+static ddf_dev_ops_t child_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
 };
@@ -64,7 +66,4 @@
 #define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
 
-/* FIXME: make this dynamic */
-#define MATCH_STRING_MAX 256
-
 /** Add formatted match id.
  *
@@ -75,29 +74,11 @@
  */
 static int usb_add_match_id(match_id_list_t *matches, int score,
-    const char *format, ...)
+    const char *match_str)
 {
-	char *match_str = NULL;
-	match_id_t *match_id = NULL;
-	int rc;
-	
-	match_str = malloc(MATCH_STRING_MAX + 1);
-	if (match_str == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-
-	/*
-	 * FIXME: replace with dynamic allocation of exact size
-	 */
-	va_list args;
-	va_start(args, format	);
-	vsnprintf(match_str, MATCH_STRING_MAX, format, args);
-	match_str[MATCH_STRING_MAX] = 0;
-	va_end(args);
-
-	match_id = create_match_id();
+	assert(matches);
+
+	match_id_t *match_id = create_match_id();
 	if (match_id == NULL) {
-		rc = ENOMEM;
-		goto failure;
+		return ENOMEM;
 	}
 
@@ -107,15 +88,4 @@
 
 	return EOK;
-	
-failure:
-	if (match_str != NULL) {
-		free(match_str);
-	}
-	if (match_id != NULL) {
-		match_id->id = NULL;
-		delete_match_id(match_id);
-	}
-	
-	return rc;
 }
 
@@ -129,7 +99,11 @@
 #define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
 	do { \
-		int __rc = usb_add_match_id((match_ids), (score), \
-		    format, ##__VA_ARGS__); \
+		char *str = NULL; \
+		int __rc = asprintf(&str, format, ##__VA_ARGS__); \
+		if (__rc > 0) { \
+			__rc = usb_add_match_id((match_ids), (score), str); \
+		} \
 		if (__rc != EOK) { \
+			free(str); \
 			return __rc; \
 		} \
@@ -150,8 +124,5 @@
     match_id_list_t *matches)
 {
-	if (desc_interface == NULL) {
-		return EINVAL;
-	}
-	if (matches == NULL) {
+	if (desc_interface == NULL || matches == NULL) {
 		return EINVAL;
 	}
@@ -314,4 +285,5 @@
     match_id_list_t *matches)
 {
+	assert(ctrl_pipe);
 	int rc;
 	/*
@@ -336,8 +308,7 @@
 /** Probe for device kind and register it in devman.
  *
- * @param[in] address Address of the (unknown) attached device.
- * @param[in] hc_handle Handle of the host controller.
+ * @param[in] ctrl_pipe Control pipe to the device.
  * @param[in] parent Parent device.
- * @param[in] dev_ops Child device ops.
+ * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
  * @param[in] dev_data Arbitrary pointer to be stored in the child
  *	as @c driver_data.
@@ -346,35 +317,22 @@
  * @return Error code.
  */
-int usb_device_register_child_in_devman(usb_address_t address,
-    devman_handle_t hc_handle, ddf_dev_t *parent,
-    ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
+int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
+    ddf_dev_t *parent, ddf_dev_ops_t *dev_ops, void *dev_data,
+    ddf_fun_t **child_fun)
 {
-	size_t this_device_name_index;
+	if (child_fun == NULL || ctrl_pipe == NULL)
+		return EINVAL;
+
+	if (!dev_ops && dev_data) {
+		usb_log_warning("Using standard fun ops with arbitrary "
+		    "driver data. This does not have to work.\n");
+	}
 
 	fibril_mutex_lock(&device_name_index_mutex);
-	this_device_name_index = device_name_index;
-	device_name_index++;
+	const size_t this_device_name_index = device_name_index++;
 	fibril_mutex_unlock(&device_name_index_mutex);
 
 	ddf_fun_t *child = NULL;
-	char *child_name = NULL;
 	int rc;
-	usb_device_connection_t dev_connection;
-	usb_pipe_t ctrl_pipe;
-
-	rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
-	if (rc != EOK) {
-		goto failure;
-	}
-
-	rc = usb_pipe_initialize_default_control(&ctrl_pipe,
-	    &dev_connection);
-	if (rc != EOK) {
-		goto failure;
-	}
-	rc = usb_pipe_probe_default_control(&ctrl_pipe);
-	if (rc != EOK) {
-		goto failure;
-	}
 
 	/*
@@ -382,6 +340,7 @@
 	 * naming etc., something more descriptive could be created.
 	 */
-	rc = asprintf(&child_name, "usb%02zu_a%d",
-	    this_device_name_index, address);
+	char child_name[12]; /* The format is: "usbAB_aXYZ", length 11 */
+	rc = snprintf(child_name, sizeof(child_name),
+	    "usb%02zu_a%d", this_device_name_index, ctrl_pipe->wire->address);
 	if (rc < 0) {
 		goto failure;
@@ -401,6 +360,19 @@
 
 	child->driver_data = dev_data;
-
-	rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
+	/* Store the attached device in fun driver data if there is no
+	 * other data */
+	if (!dev_data) {
+		usb_hub_attached_device_t *new_device = ddf_fun_data_alloc(
+		    child, sizeof(usb_hub_attached_device_t));
+		if (!new_device) {
+			rc = ENOMEM;
+			goto failure;
+		}
+		new_device->address = ctrl_pipe->wire->address;
+		new_device->fun = child;
+	}
+
+
+	rc = usb_device_create_match_ids(ctrl_pipe, &child->match_ids);
 	if (rc != EOK) {
 		goto failure;
@@ -412,19 +384,16 @@
 	}
 
-	if (child_fun != NULL) {
-		*child_fun = child;
-	}
-
+	*child_fun = child;
 	return EOK;
 
 failure:
 	if (child != NULL) {
-		child->name = NULL;
+		/* We know nothing about the data if it came from outside. */
+		if (dev_data) {
+			child->driver_data = NULL;
+		}
 		/* This takes care of match_id deallocation as well. */
 		ddf_fun_destroy(child);
 	}
-	if (child_name != NULL) {
-		free(child_name);
-	}
 
 	return rc;
Index: uspace/lib/usbdev/src/request.c
===================================================================
--- uspace/lib/usbdev/src/request.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbdev/src/request.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -250,38 +250,4 @@
 }
 
-/** Change address of connected device.
- * This function automatically updates the backing connection to point to
- * the new address.
- *
- * @param pipe Control endpoint pipe (session must be already started).
- * @param new_address New USB address to be set (in native endianness).
- * @return Error code.
- */
-int usb_request_set_address(usb_pipe_t *pipe,
-    usb_address_t new_address)
-{
-	if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
-		return EINVAL;
-	}
-
-	uint16_t addr = uint16_host2usb((uint16_t)new_address);
-
-	int rc = usb_control_request_set(pipe,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_SET_ADDRESS,
-	    addr, 0,
-	    NULL, 0);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	assert(pipe->wire != NULL);
-	/* TODO: prevent other from accessing wire now. */
-	pipe->wire->address = new_address;
-
-	return EOK;
-}
-
 /** Retrieve USB descriptor of a USB device.
  *
Index: uspace/lib/usbhid/include/usb/hid/usages/consumer.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/usages/consumer.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhid/include/usb/hid/usages/consumer.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -37,5 +37,5 @@
 #define LIBUSBHID_CONSUMER_H_
 
-const char *usbhid_multimedia_usage_to_str(int usage);
+const char *usbhid_multimedia_usage_to_str(unsigned usage);
 
 #endif /* LIBUSBHID_CONSUMER_H_ */
Index: uspace/lib/usbhid/src/consumer.c
===================================================================
--- uspace/lib/usbhid/src/consumer.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhid/src/consumer.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -38,5 +38,5 @@
 #include <usb/hid/usages/consumer.h>
 
-static const char *usbhid_consumer_usage_str[0x29d] = {
+static const char *usbhid_consumer_usage_str[] = {
 	[0x01] = "Consumer Control",
 	[0x02] = "Numeric Key Pad",
@@ -358,5 +358,5 @@
 	[0x13e] = "Reserved",
 	[0x13f] = "Reserved",
-	[0x140] = "Reserved", 
+	[0x140] = "Reserved",
 	[0x141] = "Reserved",
 	[0x142] = "Reserved",
@@ -717,12 +717,12 @@
  * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
  */
-const char *usbhid_multimedia_usage_to_str(int usage)
+const char *usbhid_multimedia_usage_to_str(unsigned usage)
 {
-	size_t map_length = sizeof(usbhid_consumer_usage_str) / sizeof(char *);
+	static const size_t map_length =
+	    sizeof(usbhid_consumer_usage_str) / sizeof(char *);
 
-	if ((usage < 0) || ((size_t)usage >= map_length))
+	if (usage >= map_length)
 		return "Unknown usage";
 
-	/*! @todo What if the usage is not in the table? */
 	return usbhid_consumer_usage_str[usage];
 }
Index: uspace/lib/usbhid/src/hiddescriptor.c
===================================================================
--- uspace/lib/usbhid/src/hiddescriptor.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhid/src/hiddescriptor.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -135,5 +135,5 @@
 int usb_hid_report_init(usb_hid_report_t *report)
 {
-	if(report == NULL) {
+	if (report == NULL) {
 		return EINVAL;
 	}
@@ -144,5 +144,5 @@
 
 	report->use_report_ids = 0;
-    return EOK;   
+    return EOK;
 }
 
Index: uspace/lib/usbhid/src/hidpath.c
===================================================================
--- uspace/lib/usbhid/src/hidpath.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhid/src/hidpath.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -385,4 +385,6 @@
 void usb_hid_report_path_free(usb_hid_report_path_t *path)
 {
+	if (path == NULL)
+		return;
 	while(!list_empty(&path->items)){
 		usb_hid_report_remove_last_item(path);
Index: uspace/lib/usbhid/src/hidreq.c
===================================================================
--- uspace/lib/usbhid/src/hidreq.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhid/src/hidreq.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -84,10 +84,10 @@
 	usb_log_debug("Sending Set Report request to the device.\n");
 	
-	rc = usb_control_request_set(ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	rc = usb_control_request_set(ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
 	    USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
 
 	if (rc != EOK) {
-		usb_log_warning("Error sending Set Report request to the "
+		usb_log_error("Error sending Set Report request to the "
 		    "device: %s.\n", str_error(rc));
 		return rc;
Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -68,9 +68,9 @@
  * @param bw_count Bandwidth compute function, passed to endpoint manager.
  */
-static inline void hcd_init(hcd_t *hcd, size_t bandwidth,
+static inline void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth,
     size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
 {
 	assert(hcd);
-	usb_device_manager_init(&hcd->dev_manager);
+	usb_device_manager_init(&hcd->dev_manager, max_speed);
 	usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count);
 	hcd->private_data = NULL;
Index: uspace/lib/usbhost/include/usb/host/usb_device_manager.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_device_manager.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhost/include/usb/host/usb_device_manager.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -59,4 +59,5 @@
 		devman_handle_t handle; /**< Devman handle of the device. */
 	} devices[USB_ADDRESS_COUNT];
+	usb_speed_t max_speed;
 	fibril_mutex_t guard;
 	/** The last reserved address */
@@ -64,13 +65,14 @@
 } usb_device_manager_t;
 
-void usb_device_manager_init(usb_device_manager_t *instance);
+void usb_device_manager_init(
+    usb_device_manager_t *instance, usb_speed_t max_speed);
 
-usb_address_t usb_device_manager_get_free_address(
-    usb_device_manager_t *instance, usb_speed_t speed);
+int usb_device_manager_request_address(usb_device_manager_t *instance,
+    usb_address_t *address, bool strict, usb_speed_t speed);
 
-int usb_device_manager_bind(usb_device_manager_t *instance,
+int usb_device_manager_bind_address(usb_device_manager_t *instance,
     usb_address_t address, devman_handle_t handle);
 
-int usb_device_manager_release(usb_device_manager_t *instance,
+int usb_device_manager_release_address(usb_device_manager_t *instance,
     usb_address_t address);
 
Index: uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -90,4 +90,7 @@
     usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
     void (*callback)(endpoint_t *, void *), void *arg);
+
+void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,
+    usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg);
 #endif
 /**
Index: uspace/lib/usbhost/src/iface.c
===================================================================
--- uspace/lib/usbhost/src/iface.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhost/src/iface.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -89,79 +89,4 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Request address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] speed Speed to associate with the new default address.
- * @param[out] address Place to write a new address.
- * @return Error code.
- */
-static int request_address(
-    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
-{
-	assert(fun);
-	hcd_t *hcd = fun_to_hcd(fun);
-	assert(hcd);
-	assert(address);
-
-	usb_log_debug("Address request speed: %s.\n", usb_str_speed(speed));
-	*address =
-	    usb_device_manager_get_free_address(&hcd->dev_manager, speed);
-	usb_log_debug("Address request with result: %d.\n", *address);
-	if (*address <= 0)
-		return *address;
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Bind address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address Address of the device
- * @param[in] handle Devman handle of the device driver.
- * @return Error code.
- */
-static int bind_address(
-  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
-{
-	assert(fun);
-	hcd_t *hcd = fun_to_hcd(fun);
-	assert(hcd);
-
-	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
-	return usb_device_manager_bind(&hcd->dev_manager, address, handle);
-}
-/*----------------------------------------------------------------------------*/
-/** Find device handle by address interface function.
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address Address in question.
- * @param[out] handle Where to store device handle if found.
- * @return Error code.
- */
-static int find_by_address(ddf_fun_t *fun, usb_address_t address,
-    devman_handle_t *handle)
-{
-	assert(fun);
-	hcd_t *hcd = fun_to_hcd(fun);
-	assert(hcd);
-	return usb_device_manager_get_info_by_address(
-	    &hcd->dev_manager, address, handle, NULL);
-}
-/*----------------------------------------------------------------------------*/
-/** Release address interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] address USB address to be released.
- * @return Error code.
- */
-static int release_address(ddf_fun_t *fun, usb_address_t address)
-{
-	assert(fun);
-	hcd_t *hcd = fun_to_hcd(fun);
-	assert(hcd);
-	usb_log_debug("Address release %d.\n", address);
-	usb_device_manager_release(&hcd->dev_manager, address);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
 static int register_helper(endpoint_t *ep, void *arg)
 {
@@ -183,7 +108,92 @@
 }
 /*----------------------------------------------------------------------------*/
+static void unregister_helper_warn(endpoint_t *ep, void *arg)
+{
+	hcd_t *hcd = arg;
+	assert(ep);
+	assert(hcd);
+	usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n",
+	    ep->address, ep->endpoint, usb_str_direction(ep->direction));
+	if (hcd->ep_remove_hook)
+		hcd->ep_remove_hook(hcd, ep);
+}
+/*----------------------------------------------------------------------------*/
+/** Request address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] speed Speed to associate with the new default address.
+ * @param[out] address Place to write a new address.
+ * @return Error code.
+ */
+static int request_address(
+    ddf_fun_t *fun, usb_address_t *address, bool strict, usb_speed_t speed)
+{
+	assert(fun);
+	hcd_t *hcd = fun_to_hcd(fun);
+	assert(hcd);
+	assert(address);
+
+	usb_log_debug("Address request: speed: %s, address: %d, strict: %s.\n",
+	    usb_str_speed(speed), *address, strict ? "YES" : "NO");
+	return usb_device_manager_request_address(
+	    &hcd->dev_manager, address, strict, speed);
+}
+/*----------------------------------------------------------------------------*/
+/** Bind address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address of the device
+ * @param[in] handle Devman handle of the device driver.
+ * @return Error code.
+ */
+static int bind_address(
+  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
+{
+	assert(fun);
+	hcd_t *hcd = fun_to_hcd(fun);
+	assert(hcd);
+
+	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
+	return usb_device_manager_bind_address(
+	    &hcd->dev_manager, address, handle);
+}
+/*----------------------------------------------------------------------------*/
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hcd_t *hcd = fun_to_hcd(fun);
+	assert(hcd);
+	return usb_device_manager_get_info_by_address(
+	    &hcd->dev_manager, address, handle, NULL);
+}
+/*----------------------------------------------------------------------------*/
+/** Release address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	assert(fun);
+	hcd_t *hcd = fun_to_hcd(fun);
+	assert(hcd);
+	usb_log_debug("Address release %d.\n", address);
+	usb_device_manager_release_address(&hcd->dev_manager, address);
+	usb_endpoint_manager_remove_address(&hcd->ep_manager, address,
+	    unregister_helper_warn, hcd);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
 static int register_endpoint(
-    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
-    usb_endpoint_t endpoint,
+    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
     usb_transfer_type_t transfer_type, usb_direction_t direction,
     size_t max_packet_size, unsigned int interval)
@@ -193,11 +203,10 @@
 	assert(hcd);
 	const size_t size = max_packet_size;
-	/* Default address is not bound or registered,
-	 * thus it does not provide speed info. */
-	usb_speed_t speed = ep_speed;
-	/* NOTE The function will return EINVAL and won't
-	 * touch speed variable for default address */
-	usb_device_manager_get_info_by_address(
+	usb_speed_t speed = USB_SPEED_MAX;
+	const int ret = usb_device_manager_get_info_by_address(
 	    &hcd->dev_manager, address, NULL, &speed);
+	if (ret != EOK) {
+		return ret;
+	}
 
 	usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n",
Index: uspace/lib/usbhost/src/usb_device_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_device_manager.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhost/src/usb_device_manager.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -38,11 +38,39 @@
 #include <usb/host/usb_device_manager.h>
 
+/** Get a free USB address
+ *
+ * @param[in] instance Device manager structure to use.
+ * @param[in] speed Speed of the device requiring address.
+ * @return Free address, or error code.
+ */
+static usb_address_t usb_device_manager_get_free_address(
+    usb_device_manager_t *instance)
+{
+
+	usb_address_t new_address = instance->last_address;
+	do {
+		new_address = (new_address + 1) % USB_ADDRESS_COUNT;
+		if (new_address == USB_ADDRESS_DEFAULT)
+			new_address = 1;
+		if (new_address == instance->last_address) {
+			return ENOSPC;
+		}
+	} while (instance->devices[new_address].occupied);
+
+	assert(new_address != USB_ADDRESS_DEFAULT);
+	instance->last_address = new_address;
+
+	return new_address;
+}
+/*----------------------------------------------------------------------------*/
 /** Initialize device manager structure.
  *
  * @param[in] instance Memory place to initialize.
+ * @param[in] max_speed Maximum allowed USB speed of devices (inclusive).
  *
  * Set all values to false/0.
  */
-void usb_device_manager_init(usb_device_manager_t *instance)
+void usb_device_manager_init(
+    usb_device_manager_t *instance, usb_speed_t max_speed)
 {
 	assert(instance);
@@ -52,45 +80,49 @@
 		instance->devices[i].speed = USB_SPEED_MAX;
 	}
-	// TODO: is this hack enough?
-	// (it is needed to allow smooth registration at default address)
-	instance->devices[0].occupied = true;
-	instance->last_address = 0;
+	instance->last_address = 1;
+	instance->max_speed = max_speed;
 	fibril_mutex_initialize(&instance->guard);
 }
 /*----------------------------------------------------------------------------*/
-/** Get a free USB address
- *
- * @param[in] instance Device manager structure to use.
- * @param[in] speed Speed of the device requiring address.
- * @return Free address, or error code.
- */
-usb_address_t usb_device_manager_get_free_address(
-    usb_device_manager_t *instance, usb_speed_t speed)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-
-	usb_address_t new_address = instance->last_address;
-	do {
-		++new_address;
-		if (new_address > USB11_ADDRESS_MAX)
-			new_address = 1; // NOTE it should be safe to put 0 here
-			                 // TODO Use mod
-		if (new_address == instance->last_address) {
+/** Request USB address.
+ * @param instance usb_device_manager
+ * @param address Pointer to requested address value, place to store new address
+ * @parma strict Fail if the requested address is not available.
+ * @return Error code.
+ * @note Default address is only available in strict mode.
+ */
+int usb_device_manager_request_address(usb_device_manager_t *instance,
+    usb_address_t *address, bool strict, usb_speed_t speed)
+{
+	assert(instance);
+	assert(address);
+	if (speed > instance->max_speed)
+		return ENOTSUP;
+
+	if ((*address) < 0 || (*address) >= USB_ADDRESS_COUNT)
+		return EINVAL;
+
+	fibril_mutex_lock(&instance->guard);
+	/* Only grant default address to strict requests */
+	if (( (*address) == USB_ADDRESS_DEFAULT) && !strict) {
+		*address = instance->last_address;
+	}
+
+	if (instance->devices[*address].occupied) {
+		if (strict) {
 			fibril_mutex_unlock(&instance->guard);
-			return ENOSPC;
+			return ENOENT;
 		}
-	} while (instance->devices[new_address].occupied);
-
-	assert(new_address != USB_ADDRESS_DEFAULT);
-	assert(instance->devices[new_address].occupied == false);
-	assert(instance->devices[new_address].handle == 0);
-
-	instance->devices[new_address].occupied = true;
-	instance->devices[new_address].speed = speed;
-	instance->last_address = new_address;
-
-	fibril_mutex_unlock(&instance->guard);
-	return new_address;
+		*address = usb_device_manager_get_free_address(instance);
+	}
+	assert(instance->devices[*address].occupied == false);
+	assert(instance->devices[*address].handle == 0);
+	assert(*address != USB_ADDRESS_DEFAULT || strict);
+
+	instance->devices[*address].occupied = true;
+	instance->devices[*address].speed = speed;
+
+	fibril_mutex_unlock(&instance->guard);
+	return EOK;
 }
 /*----------------------------------------------------------------------------*/
@@ -102,5 +134,5 @@
  * @return Error code.
  */
-int usb_device_manager_bind(usb_device_manager_t *instance,
+int usb_device_manager_bind_address(usb_device_manager_t *instance,
     usb_address_t address, devman_handle_t handle)
 {
@@ -132,8 +164,8 @@
  * @return Error code.
  */
-int usb_device_manager_release(
+int usb_device_manager_release_address(
     usb_device_manager_t *instance, usb_address_t address)
 {
-	if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
+	if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
 		return EINVAL;
 	}
@@ -188,5 +220,5 @@
 {
 	assert(instance);
-	if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
+	if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
 		return EINVAL;
 	}
Index: uspace/lib/usbhost/src/usb_endpoint_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision 27ca3a3e5448cd0c42a1d62d96d92cce18a2fc0f)
+++ uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision c2245a30ec71d59d19f3b4dc70b0684e812e229b)
@@ -384,2 +384,21 @@
 	return EOK;
 }
+/*----------------------------------------------------------------------------*/
+void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,
+    usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg)
+{
+	assert(address >= 0);
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	list_foreach(*get_list(instance, address), iterator) {
+		endpoint_t *ep = endpoint_get_instance(iterator);
+		if (ep->address == address) {
+			iterator = iterator->next;
+			list_remove(&ep->link);
+			if (callback)
+				callback(ep, arg);
+			endpoint_destroy(ep);
+		}
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
