Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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 6088193ffd64c208e1c21d029a45e322957f7e72)
+++ 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);
+}
