Index: uspace/app/netstart/self_test.c
===================================================================
--- uspace/app/netstart/self_test.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ 	(revision )
@@ -1,334 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup net
- * @{
- */
-
-/** @file
- * Networking self-tests implementation.
- *
- */
-
-#include <errno.h>
-#include <malloc.h>
-#include <stdio.h>
-
-#include <net_checksum.h>
-#include <adt/int_map.h>
-#include <adt/char_map.h>
-#include <adt/generic_char_map.h>
-#include <adt/measured_strings.h>
-#include <adt/dynamic_fifo.h>
-
-#include "self_test.h"
-
-/** Test the statement, compare the result and evaluate.
- *
- * @param[in] statement The statement to test.
- * @param[in] result    The expected result.
- *
- */
-#define TEST(statement, result) \
-	do { \
-		printf("\n\t%s == %s", #statement, #result); \
-		if ((statement) != (result)) { \
-			printf("\tfailed\n"); \
-			fprintf(stderr, "\nNetwork self-test failed\n"); \
-			return EINVAL; \
-		} else \
-			printf("\tOK"); \
-	} while (0)
-
-#define XMALLOC(var, type) \
-	do { \
-		(var) = (type *) malloc(sizeof(type)); \
-		if ((var) == NULL) { \
-			fprintf(stderr, "\nMemory allocation error\n"); \
-			return ENOMEM; \
-		} \
-	} while (0)
-
-GENERIC_CHAR_MAP_DECLARE(int_char_map, int);
-GENERIC_CHAR_MAP_IMPLEMENT(int_char_map, int);
-
-GENERIC_FIELD_DECLARE(int_field, int);
-GENERIC_FIELD_IMPLEMENT(int_field, int);
-
-INT_MAP_DECLARE(int_map, int);
-INT_MAP_IMPLEMENT(int_map, int);
-
-/** Self-test start function.
- *
- * Run all self-tests.
- *
- * @returns EOK on success.
- * @returns The first error occurred.
- *
- */
-int self_test(void)
-{
-	printf("Running networking self-tests\n");
-	
-	printf("\nChar map test");
-	char_map_t cm;
-	
-	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
-	TEST(char_map_initialize(&cm), EOK);
-	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
-	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
-	TEST(char_map_add(&cm, "bla", 0, 1), EOK);
-	TEST(char_map_find(&cm, "bla", 0), 1);
-	TEST(char_map_add(&cm, "bla", 0, 10), EEXISTS);
-	TEST(char_map_update(&cm, "bla", 0, 2), EOK);
-	TEST(char_map_find(&cm, "bla", 0), 2);
-	TEST(char_map_update(&cm, "ucho", 0, 2), EOK);
-	TEST(char_map_exclude(&cm, "bla", 0), 2);
-	TEST(char_map_exclude(&cm, "bla", 0), CHAR_MAP_NULL);
-	TEST(char_map_find(&cm, "ucho", 0), 2);
-	TEST(char_map_update(&cm, "ucho", 0, 3), EOK);
-	TEST(char_map_find(&cm, "ucho", 0), 3);
-	TEST(char_map_add(&cm, "blabla", 0, 5), EOK);
-	TEST(char_map_find(&cm, "blabla", 0), 5);
-	TEST(char_map_add(&cm, "bla", 0, 6), EOK);
-	TEST(char_map_find(&cm, "bla", 0), 6);
-	TEST(char_map_exclude(&cm, "bla", 0), 6);
-	TEST(char_map_find(&cm, "bla", 0), CHAR_MAP_NULL);
-	TEST(char_map_find(&cm, "blabla", 0), 5);
-	TEST(char_map_add(&cm, "auto", 0, 7), EOK);
-	TEST(char_map_find(&cm, "auto", 0), 7);
-	TEST(char_map_add(&cm, "kara", 0, 8), EOK);
-	TEST(char_map_find(&cm, "kara", 0), 8);
-	TEST(char_map_add(&cm, "nic", 0, 9), EOK);
-	TEST(char_map_find(&cm, "nic", 0), 9);
-	TEST(char_map_find(&cm, "blabla", 0), 5);
-	TEST(char_map_add(&cm, "micnicnic", 5, 9), EOK);
-	TEST(char_map_find(&cm, "micni", 0), 9);
-	TEST(char_map_find(&cm, "micnicn", 5), 9);
-	TEST(char_map_add(&cm, "\x10\x0\x2\x2", 4, 15), EOK);
-	TEST(char_map_find(&cm, "\x10\x0\x2\x2", 4), 15);
-	
-	TEST((char_map_destroy(&cm), EOK), EOK);
-	TEST(char_map_update(&cm, "ucho", 0, 3), EINVAL);
-	
-	printf("\nCRC computation test");
-	uint32_t value;
-	
-	TEST(value = ~compute_crc32(~0, "123456789", 8 * 9), 0xcbf43926);
-	TEST(value = ~compute_crc32(~0, "1", 8), 0x83dcefb7);
-	TEST(value = ~compute_crc32(~0, "12", 8 * 2), 0x4f5344cd);
-	TEST(value = ~compute_crc32(~0, "123", 8 * 3), 0x884863d2);
-	TEST(value = ~compute_crc32(~0, "1234", 8 * 4), 0x9be3e0a3);
-	TEST(value = ~compute_crc32(~0, "12345678", 8 * 8), 0x9ae0daaf);
-	TEST(value = ~compute_crc32(~0, "ahoj pane", 8 * 9), 0x5fc3d706);
-	
-	printf("\nDynamic fifo test");
-	dyn_fifo_t fifo;
-	
-	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
-	TEST(dyn_fifo_initialize(&fifo, 1), EOK);
-	TEST(dyn_fifo_push(&fifo, 1, 0), EOK);
-	TEST(dyn_fifo_pop(&fifo), 1);
-	TEST(dyn_fifo_pop(&fifo), ENOENT);
-	TEST(dyn_fifo_push(&fifo, 2, 1), EOK);
-	TEST(dyn_fifo_push(&fifo, 3, 1), ENOMEM);
-	TEST(dyn_fifo_push(&fifo, 3, 0), EOK);
-	TEST(dyn_fifo_pop(&fifo), 2);
-	TEST(dyn_fifo_pop(&fifo), 3);
-	TEST(dyn_fifo_push(&fifo, 4, 2), EOK);
-	TEST(dyn_fifo_push(&fifo, 5, 2), EOK);
-	TEST(dyn_fifo_push(&fifo, 6, 2), ENOMEM);
-	TEST(dyn_fifo_push(&fifo, 6, 5), EOK);
-	TEST(dyn_fifo_push(&fifo, 7, 5), EOK);
-	TEST(dyn_fifo_pop(&fifo), 4);
-	TEST(dyn_fifo_pop(&fifo), 5);
-	TEST(dyn_fifo_push(&fifo, 8, 5), EOK);
-	TEST(dyn_fifo_push(&fifo, 9, 5), EOK);
-	TEST(dyn_fifo_push(&fifo, 10, 6), EOK);
-	TEST(dyn_fifo_push(&fifo, 11, 6), EOK);
-	TEST(dyn_fifo_pop(&fifo), 6);
-	TEST(dyn_fifo_pop(&fifo), 7);
-	TEST(dyn_fifo_push(&fifo, 12, 6), EOK);
-	TEST(dyn_fifo_push(&fifo, 13, 6), EOK);
-	TEST(dyn_fifo_push(&fifo, 14, 6), ENOMEM);
-	TEST(dyn_fifo_push(&fifo, 14, 8), EOK);
-	TEST(dyn_fifo_pop(&fifo), 8);
-	TEST(dyn_fifo_pop(&fifo), 9);
-	TEST(dyn_fifo_pop(&fifo), 10);
-	TEST(dyn_fifo_pop(&fifo), 11);
-	TEST(dyn_fifo_pop(&fifo), 12);
-	TEST(dyn_fifo_pop(&fifo), 13);
-	TEST(dyn_fifo_pop(&fifo), 14);
-	TEST(dyn_fifo_destroy(&fifo), EOK);
-	TEST(dyn_fifo_push(&fifo, 1, 0), EINVAL);
-	
-	printf("\nGeneric char map test");
-	
-	int *x;
-	int *y;
-	int *z;
-	int *u;
-	int *v;
-	int *w;
-	
-	XMALLOC(x, int);
-	XMALLOC(y, int);
-	XMALLOC(z, int);
-	XMALLOC(u, int);
-	XMALLOC(v, int);
-	XMALLOC(w, int);
-	
-	int_char_map_t icm;
-	icm.magic = 0;
-	
-	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
-	TEST(int_char_map_initialize(&icm), EOK);
-	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
-	TEST(int_char_map_find(&icm, "bla", 0), NULL);
-	TEST(int_char_map_add(&icm, "bla", 0, x), EOK);
-	TEST(int_char_map_find(&icm, "bla", 0), x);
-	TEST(int_char_map_add(&icm, "bla", 0, y), EEXISTS);
-	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
-	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
-	TEST(int_char_map_add(&icm, "blabla", 0, v), EOK);
-	TEST(int_char_map_find(&icm, "blabla", 0), v);
-	TEST(int_char_map_add(&icm, "bla", 0, w), EOK);
-	TEST(int_char_map_find(&icm, "bla", 0), w);
-	TEST((int_char_map_exclude(&icm, "bla", 0), EOK), EOK);
-	TEST(int_char_map_find(&icm, "bla", 0), NULL);
-	TEST(int_char_map_find(&icm, "blabla", 0), v);
-	TEST(int_char_map_add(&icm, "auto", 0, u), EOK);
-	TEST(int_char_map_find(&icm, "auto", 0), u);
-	TEST((int_char_map_destroy(&icm), EOK), EOK);
-	TEST(int_char_map_add(&icm, "ucho", 0, z), EINVAL);
-	
-	printf("\nGeneric field test");
-	
-	XMALLOC(x, int);
-	XMALLOC(y, int);
-	XMALLOC(z, int);
-	XMALLOC(u, int);
-	XMALLOC(v, int);
-	XMALLOC(w, int);
-	
-	int_field_t gf;
-	gf.magic = 0;
-	
-	TEST(int_field_add(&gf, x), EINVAL);
-	TEST(int_field_count(&gf), -1);
-	TEST(int_field_initialize(&gf), EOK);
-	TEST(int_field_count(&gf), 0);
-	TEST(int_field_get_index(&gf, 1), NULL);
-	TEST(int_field_add(&gf, x), 0);
-	TEST(int_field_get_index(&gf, 0), x);
-	TEST((int_field_exclude_index(&gf, 0), EOK), EOK);
-	TEST(int_field_get_index(&gf, 0), NULL);
-	TEST(int_field_add(&gf, y), 1);
-	TEST(int_field_get_index(&gf, 1), y);
-	TEST(int_field_add(&gf, z), 2);
-	TEST(int_field_get_index(&gf, 2), z);
-	TEST(int_field_get_index(&gf, 1), y);
-	TEST(int_field_count(&gf), 3);
-	TEST(int_field_add(&gf, u), 3);
-	TEST(int_field_get_index(&gf, 3), u);
-	TEST(int_field_add(&gf, v), 4);
-	TEST(int_field_get_index(&gf, 4), v);
-	TEST(int_field_add(&gf, w), 5);
-	TEST(int_field_get_index(&gf, 5), w);
-	TEST(int_field_count(&gf), 6);
-	TEST((int_field_exclude_index(&gf, 1), EOK), EOK);
-	TEST(int_field_get_index(&gf, 1), NULL);
-	TEST(int_field_get_index(&gf, 3), u);
-	TEST((int_field_exclude_index(&gf, 7), EOK), EOK);
-	TEST(int_field_get_index(&gf, 3), u);
-	TEST(int_field_get_index(&gf, 5), w);
-	TEST((int_field_exclude_index(&gf, 4), EOK), EOK);
-	TEST(int_field_get_index(&gf, 4), NULL);
-	TEST((int_field_destroy(&gf), EOK), EOK);
-	TEST(int_field_count(&gf), -1);
-	
-	printf("\nInt map test");
-	
-	XMALLOC(x, int);
-	XMALLOC(y, int);
-	XMALLOC(z, int);
-	XMALLOC(u, int);
-	XMALLOC(v, int);
-	XMALLOC(w, int);
-	
-	int_map_t im;
-	im.magic = 0;
-	
-	TEST(int_map_add(&im, 1, x), EINVAL);
-	TEST(int_map_count(&im), -1);
-	TEST(int_map_initialize(&im), EOK);
-	TEST(int_map_count(&im), 0);
-	TEST(int_map_find(&im, 1), NULL);
-	TEST(int_map_add(&im, 1, x), 0);
-	TEST(int_map_find(&im, 1), x);
-	TEST((int_map_exclude(&im, 1), EOK), EOK);
-	TEST(int_map_find(&im, 1), NULL);
-	TEST(int_map_add(&im, 1, y), 1);
-	TEST(int_map_find(&im, 1), y);
-	TEST(int_map_add(&im, 4, z), 2);
-	TEST(int_map_get_index(&im, 2), z);
-	TEST(int_map_find(&im, 4), z);
-	TEST(int_map_find(&im, 1), y);
-	TEST(int_map_count(&im), 3);
-	TEST(int_map_add(&im, 2, u), 3);
-	TEST(int_map_find(&im, 2), u);
-	TEST(int_map_add(&im, 3, v), 4);
-	TEST(int_map_find(&im, 3), v);
-	TEST(int_map_get_index(&im, 4), v);
-	TEST(int_map_add(&im, 6, w), 5);
-	TEST(int_map_find(&im, 6), w);
-	TEST(int_map_count(&im), 6);
-	TEST((int_map_exclude(&im, 1), EOK), EOK);
-	TEST(int_map_find(&im, 1), NULL);
-	TEST(int_map_find(&im, 2), u);
-	TEST((int_map_exclude(&im, 7), EOK), EOK);
-	TEST(int_map_find(&im, 2), u);
-	TEST(int_map_find(&im, 6), w);
-	TEST((int_map_exclude_index(&im, 4), EOK), EOK);
-	TEST(int_map_get_index(&im, 4), NULL);
-	TEST(int_map_find(&im, 3), NULL);
-	TEST((int_map_destroy(&im), EOK), EOK);
-	TEST(int_map_count(&im), -1);
-	
-	printf("\nMeasured strings test");
-	
-	measured_string_ref string =
-	    measured_string_create_bulk("I am a measured string!", 0);
-	printf("\n%x, %s at %x of %d\n", string, string->value, string->value,
-	    string->length);
-	
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/app/netstart/self_test.h
===================================================================
--- uspace/app/netstart/self_test.h	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ 	(revision )
@@ -1,41 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup net
- * @{
- */
-
-#ifndef __SELF_TEST_H__
-#define __SELF_TEST_H__
-
-extern int self_test(void);
-
-#endif
-
-/** @}
- */
Index: uspace/drv/ehci-hcd/hc_iface.c
===================================================================
--- uspace/drv/ehci-hcd/hc_iface.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/drv/ehci-hcd/hc_iface.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -123,4 +123,5 @@
  * @param[in] fun Device function the action was invoked on.
  * @param[in] address USB address of the device.
+ * @param[in] speed Endpoint speed (invalid means to use device one).
  * @param[in] endpoint Endpoint number.
  * @param[in] transfer_type USB transfer type.
@@ -131,5 +132,5 @@
  */
 static int register_endpoint(ddf_fun_t *fun,
-    usb_address_t address, usb_endpoint_t endpoint,
+    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
     usb_transfer_type_t transfer_type, usb_direction_t direction,
     size_t max_packet_size, unsigned int interval)
@@ -165,5 +166,4 @@
  * @param[in] fun Device function the action was invoked on.
  * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] max_packet_size Max packet size for the transfer.
  * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
  *	by the caller).
@@ -174,5 +174,5 @@
  */
 static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
+    void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
@@ -191,5 +191,4 @@
  * @param[in] fun Device function the action was invoked on.
  * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] max_packet_size Max packet size for the transfer.
  * @param[in] data Buffer where to store the data (in USB endianess,
  *	allocated and deallocated by the caller).
@@ -200,5 +199,5 @@
  */
 static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
+    void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
@@ -217,5 +216,4 @@
  * @param[in] fun Device function the action was invoked on.
  * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] max_packet_size Max packet size for the transfer.
  * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
  *	by the caller).
@@ -226,5 +224,5 @@
  */
 static int bulk_out(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
+    void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
@@ -243,5 +241,4 @@
  * @param[in] fun Device function the action was invoked on.
  * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] max_packet_size Max packet size for the transfer.
  * @param[in] data Buffer where to store the data (in USB endianess,
  *	allocated and deallocated by the caller).
@@ -252,5 +249,5 @@
  */
 static int bulk_in(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size, void *data, size_t size,
+    void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
@@ -269,5 +266,4 @@
  * @param[in] fun Device function the action was invoked on.
  * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] max_packet_size Max packet size for the transfer.
  * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
  *	and deallocated by the caller).
@@ -281,5 +277,4 @@
  */
 static int control_write(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
     void *setup_packet, size_t setup_packet_size,
     void *data_buffer, size_t data_buffer_size,
@@ -300,5 +295,4 @@
  * @param[in] fun Device function the action was invoked on.
  * @param[in] target Target pipe (address and endpoint number) specification.
- * @param[in] max_packet_size Max packet size for the transfer.
  * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
  *	and deallocated by the caller).
@@ -312,5 +306,4 @@
  */
 static int control_read(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
     void *setup_packet, size_t setup_packet_size,
     void *data_buffer, size_t data_buffer_size,
Index: uspace/drv/ohci/iface.c
===================================================================
--- uspace/drv/ohci/iface.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/drv/ohci/iface.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -197,6 +197,18 @@
 }
 /*----------------------------------------------------------------------------*/
-static int register_endpoint(
-    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
+/** Register endpoint for bandwidth reservation.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] ep_speed Endpoint speed (invalid means to use device one).
+ * @param[in] endpoint Endpoint number.
+ * @param[in] transfer_type USB transfer type.
+ * @param[in] direction Endpoint data direction.
+ * @param[in] max_packet_size Max packet size of the endpoint.
+ * @param[in] interval Polling interval.
+ * @return Error code.
+ */
+static int register_endpoint(ddf_fun_t *fun,
+    usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,
     usb_transfer_type_t transfer_type, usb_direction_t direction,
     size_t max_packet_size, unsigned int interval)
@@ -204,6 +216,10 @@
 	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
-	const usb_speed_t speed =
-	    usb_device_keeper_get_speed(&hc->manager, address);
+	if (address == hc->rh.address)
+		return EOK;
+	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
+	if (speed >= USB_SPEED_MAX) {
+		speed = ep_speed;
+	}
 	const size_t size =
 	    (transfer_type == USB_TRANSFER_INTERRUPT
@@ -243,21 +259,31 @@
 	usb_log_debug("Unregister endpoint %d:%d %d.\n",
 	    address, endpoint, direction);
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
+	    address, endpoint, direction, NULL);
+	if (ep != NULL) {
+		usb_device_keeper_del_ep(&hc->manager, address, ep);
+	}
 	return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
 	    endpoint, direction);
 }
 /*----------------------------------------------------------------------------*/
-/** Interrupt out transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts
- * @param[in] data Source of data.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion
- * @param[in] arg Additional for callback function.
+/** Schedule interrupt out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
  * @return Error code.
  */
 static int interrupt_out(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    ddf_fun_t *fun, usb_target_t target, void *data,
     size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
@@ -276,17 +302,22 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Interrupt in transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts
- * @param[out] data Data destination.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion
- * @param[in] arg Additional for callback function.
+/** Schedule interrupt in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
  * @return Error code.
  */
 static int interrupt_in(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    ddf_fun_t *fun, usb_target_t target, void *data,
     size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
@@ -305,17 +336,22 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Bulk out transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts
- * @param[in] data Source of data.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion
- * @param[in] arg Additional for callback function.
+/** Schedule bulk out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
  * @return Error code.
  */
 static int bulk_out(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    ddf_fun_t *fun, usb_target_t target, void *data,
     size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
@@ -334,17 +370,22 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Bulk in transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts
- * @param[out] data Data destination.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion
- * @param[in] arg Additional for callback function.
+/** Schedule bulk in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
  * @return Error code.
  */
 static int bulk_in(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    ddf_fun_t *fun, usb_target_t target, void *data,
     size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
@@ -363,19 +404,25 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Control write transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts.
- * @param[in] setup_data Data to send with SETUP transfer.
- * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
- * @param[in] data Source of data.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion.
- * @param[in] arg Additional for callback function.
+/** Schedule control write transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Data buffer (in USB endianess, allocated and
+ *	deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
  * @return Error code.
  */
 static int control_write(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
+    ddf_fun_t *fun, usb_target_t target,
     void *setup_data, size_t setup_size, void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
@@ -397,19 +444,25 @@
 }
 /*----------------------------------------------------------------------------*/
-/** Control read transaction interface function
- *
- * @param[in] fun DDF function that was called.
- * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts.
- * @param[in] setup_data Data to send with SETUP packet.
- * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
- * @param[out] data Source of data.
- * @param[in] size Size of data source.
- * @param[in] callback Function to call on transaction completion.
- * @param[in] arg Additional for callback function.
+/** Schedule control read transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
  * @return Error code.
  */
 static int control_read(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
+    ddf_fun_t *fun, usb_target_t target,
     void *setup_data, size_t setup_size, void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/drv/uhci-hcd/iface.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -74,6 +74,6 @@
 	    name, target.address, target.endpoint, size, ep->max_packet_size);
 
-	assert(ep->speed ==
-	    usb_device_keeper_get_speed(&(*hc)->manager, target.address));
+//	assert(ep->speed ==
+//	    usb_device_keeper_get_speed(&(*hc)->manager, target.address));
 //	assert(ep->max_packet_size == max_packet_size);
 //	assert(ep->transfer_type == USB_TRANSFER_CONTROL);
@@ -198,5 +198,6 @@
 /*----------------------------------------------------------------------------*/
 static int register_endpoint(
-    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
+    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
+    usb_endpoint_t endpoint,
     usb_transfer_type_t transfer_type, usb_direction_t direction,
     size_t max_packet_size, unsigned int interval)
@@ -204,7 +205,12 @@
 	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
-	const usb_speed_t speed =
-	    usb_device_keeper_get_speed(&hc->manager, address);
-	const size_t size = max_packet_size;
+	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
+	if (speed >= USB_SPEED_MAX) {
+		speed = ep_speed;
+	}
+	const size_t size =
+	    (transfer_type == USB_TRANSFER_INTERRUPT
+	    || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
+	    max_packet_size : 0;
 	int ret;
 
@@ -240,4 +246,9 @@
 	usb_log_debug("Unregister endpoint %d:%d %d.\n",
 	    address, endpoint, direction);
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
+	    address, endpoint, direction, NULL);
+	if (ep != NULL) {
+		usb_device_keeper_del_ep(&hc->manager, address, ep);
+	}
 	return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
 	    endpoint, direction);
@@ -248,5 +259,4 @@
  * @param[in] fun DDF function that was called.
  * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts
  * @param[in] data Source of data.
  * @param[in] size Size of data source.
@@ -256,5 +266,5 @@
  */
 static int interrupt_out(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    ddf_fun_t *fun, usb_target_t target, void *data,
     size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
@@ -277,5 +287,4 @@
  * @param[in] fun DDF function that was called.
  * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts
  * @param[out] data Data destination.
  * @param[in] size Size of data source.
@@ -285,5 +294,5 @@
  */
 static int interrupt_in(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    ddf_fun_t *fun, usb_target_t target, void *data,
     size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
@@ -306,5 +315,4 @@
  * @param[in] fun DDF function that was called.
  * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts
  * @param[in] data Source of data.
  * @param[in] size Size of data source.
@@ -314,5 +322,5 @@
  */
 static int bulk_out(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    ddf_fun_t *fun, usb_target_t target, void *data,
     size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
 {
@@ -335,5 +343,4 @@
  * @param[in] fun DDF function that was called.
  * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts
  * @param[out] data Data destination.
  * @param[in] size Size of data source.
@@ -343,5 +350,5 @@
  */
 static int bulk_in(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data,
+    ddf_fun_t *fun, usb_target_t target, void *data,
     size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
 {
@@ -364,5 +371,4 @@
  * @param[in] fun DDF function that was called.
  * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts.
  * @param[in] setup_data Data to send with SETUP transfer.
  * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
@@ -374,5 +380,5 @@
  */
 static int control_write(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
+    ddf_fun_t *fun, usb_target_t target,
     void *setup_data, size_t setup_size, void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
@@ -398,5 +404,4 @@
  * @param[in] fun DDF function that was called.
  * @param[in] target USB device to write to.
- * @param[in] max_packet_size maximum size of data packet the device accepts.
  * @param[in] setup_data Data to send with SETUP packet.
  * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
@@ -408,5 +413,5 @@
  */
 static int control_read(
-    ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,
+    ddf_fun_t *fun, usb_target_t target,
     void *setup_data, size_t setup_size, void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/drv/vhc/connhost.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -257,5 +257,4 @@
 
 static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
     void *data, size_t size,
     usbhc_iface_transfer_out_callback_t callback, void *arg)
@@ -267,5 +266,4 @@
 
 static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
     void *data, size_t size,
     usbhc_iface_transfer_in_callback_t callback, void *arg)
@@ -277,5 +275,4 @@
 
 static int control_write(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
     void *setup_packet, size_t setup_packet_size,
     void *data, size_t data_size,
@@ -295,5 +292,4 @@
 
 static int control_read(ddf_fun_t *fun, usb_target_t target,
-    size_t max_packet_size,
     void *setup_packet, size_t setup_packet_size,
     void *data, size_t data_size,
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -270,5 +270,4 @@
 	}
 
-	size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
 	usb_target_t target = {
 		.address = DEV_IPC_GET_ARG1(*call),
@@ -300,5 +299,5 @@
 	trans->size = len;
 
-	rc = transfer_func(fun, target, max_packet_size,
+	rc = transfer_func(fun, target,
 	    buffer, len,
 	    callback_out, trans);
@@ -326,5 +325,4 @@
 	}
 
-	size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
 	usb_target_t target = {
 		.address = DEV_IPC_GET_ARG1(*call),
@@ -348,5 +346,5 @@
 	trans->size = len;
 
-	int rc = transfer_func(fun, target, max_packet_size,
+	int rc = transfer_func(fun, target,
 	    trans->buffer, len,
 	    callback_in, trans);
@@ -414,5 +412,4 @@
 	};
 	size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
-	size_t max_packet_size = DEV_IPC_GET_ARG4(*call);
 
 	int rc;
@@ -450,5 +447,5 @@
 	trans->size = data_buffer_len;
 
-	rc = usb_iface->control_write(fun, target, max_packet_size,
+	rc = usb_iface->control_write(fun, target,
 	    setup_packet, setup_packet_len,
 	    data_buffer, data_buffer_len,
@@ -477,5 +474,4 @@
 		.endpoint = DEV_IPC_GET_ARG2(*call)
 	};
-	size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
 
 	int rc;
@@ -515,5 +511,5 @@
 	}
 
-	rc = usb_iface->control_read(fun, target, max_packet_size,
+	rc = usb_iface->control_read(fun, target,
 	    setup_packet, setup_packet_len,
 	    trans->buffer, trans->size,
@@ -537,21 +533,32 @@
 	}
 
-#define INIT_FROM_HIGH_DATA(type, var, arg_no) \
-	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256
-#define INIT_FROM_LOW_DATA(type, var, arg_no) \
-	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256
-
-	INIT_FROM_HIGH_DATA(usb_address_t, address, 1);
-	INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1);
-	INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2);
-	INIT_FROM_LOW_DATA(usb_direction_t, direction, 2);
-
-#undef INIT_FROM_HIGH_DATA
-#undef INIT_FROM_LOW_DATA
-
-	size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call);
-	unsigned int interval  = (unsigned int) DEV_IPC_GET_ARG4(*call);
-
-	int rc = usb_iface->register_endpoint(fun, address, endpoint,
+#define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
+	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 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)
+
+	_INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);
+	_INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);
+
+	_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(size_t, max_packet_size, 3);
+	_INIT_FROM_LOW_DATA2(unsigned int, interval, 3);
+
+#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, address, speed, endpoint,
 	    transfer_type, direction, max_packet_size, interval);
 
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -66,5 +66,4 @@
  *   - argument #1 is target address
  *   - argument #2 is target endpoint
- *   - argument #3 is max packet size of the endpoint
  * - this call is immediately followed by IPC data read (async version)
  * - the call is not answered until the device returns some data (or until
@@ -169,9 +168,12 @@
 	/** Register endpoint attributes at host controller.
 	 * This is used to reserve portion of USB bandwidth.
+	 * When speed is invalid, speed of the device is used.
 	 * Parameters:
-	 * - USB address + endpoint number (ADDR * 256 + EP)
-	 * - transfer type + direction (TYPE * 256 + DIR)
-	 * - maximum packet size
-	 * - interval (in milliseconds)
+	 * - USB address + endpoint number
+	 *   - packed as ADDR << 16 + EP
+	 * - speed + transfer type + direction
+	 *   - packed as ( SPEED << 8 + TYPE ) << 8 + DIR
+	 * - maximum packet size + interval (in milliseconds)
+	 *   - packed as MPS << 16 + INT
 	 * Answer:
 	 * - EOK - reservation successful
@@ -202,5 +204,5 @@
 
 /** Out transfer processing function prototype. */
-typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t,
+typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,
     void *, size_t,
     usbhc_iface_transfer_out_callback_t, void *);
@@ -210,5 +212,5 @@
 
 /** In transfer processing function prototype. */
-typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t,
+typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,
     void *, size_t,
     usbhc_iface_transfer_in_callback_t, void *);
@@ -222,5 +224,6 @@
 	int (*release_address)(ddf_fun_t *, usb_address_t);
 
-	int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
+	int (*register_endpoint)(ddf_fun_t *,
+	    usb_address_t, usb_speed_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,
@@ -234,10 +237,8 @@
 
 	int (*control_write)(ddf_fun_t *, usb_target_t,
-	    size_t,
 	    void *, size_t, void *, size_t,
 	    usbhc_iface_transfer_out_callback_t, void *);
 
 	int (*control_read)(ddf_fun_t *, usb_target_t,
-	    size_t,
 	    void *, size_t, void *, size_t,
 	    usbhc_iface_transfer_in_callback_t, void *);
Index: uspace/lib/packet/include/net_byteorder.h
===================================================================
--- uspace/lib/packet/include/net_byteorder.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
+++ uspace/lib/packet/include/net_byteorder.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Host - network byte order manipulation functions.
+ */
+
+#ifndef __NET_BYTEORDER_H__
+#define __NET_BYTEORDER_H__
+
+#include <byteorder.h>
+#include <sys/types.h>
+
+
+/** Converts the given short number (16 bit) from the host byte order to the network byte order (big endian).
+ *  @param[in] number The number in the host byte order to be converted.
+ *  @returns The number in the network byte order.
+ */
+#define htons(number)		host2uint16_t_be(number)
+
+/** Converts the given long number (32 bit) from the host byte order to the network byte order (big endian).
+ *  @param[in] number The number in the host byte order to be converted.
+ *  @returns The number in the network byte order.
+ */
+#define htonl(number)		host2uint32_t_be(number)
+
+/** Converts the given short number (16 bit) from the network byte order (big endian) to the host byte order.
+ *  @param[in] number The number in the network byte order to be converted.
+ *  @returns The number in the host byte order.
+ */
+#define ntohs(number) 	uint16_t_be2host(number)
+
+/** Converts the given long number (32 bit) from the network byte order (big endian) to the host byte order.
+ *  @param[in] number The number in the network byte order to be converted.
+ *  @returns The number in the host byte order.
+ */
+#define ntohl(number)		uint32_t_be2host(number)
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/packet/include/net_err.h
===================================================================
--- uspace/lib/packet/include/net_err.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
+++ uspace/lib/packet/include/net_err.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ * @{
+ */
+
+/** @file
+ * Common error processing codes and routines.
+ */
+
+#ifndef __NET_ERR_H__
+#define __NET_ERR_H__
+
+#include <errno.h>
+
+#ifdef CONFIG_DEBUG
+	#include <stdio.h>
+	#include <str_error.h>
+#endif
+
+/** An actual stored error code.
+ *
+ */
+#define ERROR_CODE  error_check_return_value
+
+/** An error processing routines declaration.
+ *
+ * This has to be declared in the block where the error processing
+ * is desired.
+ *
+ */
+#define ERROR_DECLARE  int ERROR_CODE
+
+/** Store the value as an error code and checks if an error occurred.
+ *
+ * @param[in] value The value to be checked. May be a function call.
+ * @return False if the value indicates success (EOK).
+ * @return True otherwise.
+ *
+ */
+#ifdef CONFIG_DEBUG
+
+#define ERROR_OCCURRED(value) \
+	(((ERROR_CODE = (value)) != EOK) \
+	&& ({ \
+		fprintf(stderr, "libsocket error at %s:%d (%s)\n", \
+		__FILE__, __LINE__, str_error(ERROR_CODE)); \
+		1; \
+	}))
+
+#else
+
+#define ERROR_OCCURRED(value)  ((ERROR_CODE = (value)) != EOK)
+
+#endif
+
+/** Error propagation
+ *
+ * Check if an error occurred and immediately exit the actual
+ * function returning the error code.
+ *
+ * @param[in] value The value to be checked. May be a function call.
+ *
+ */
+
+#define ERROR_PROPAGATE(value) \
+	if (ERROR_OCCURRED(value)) \
+		return ERROR_CODE
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/packet/include/socket_errno.h
===================================================================
--- uspace/lib/packet/include/socket_errno.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
+++ uspace/lib/packet/include/socket_errno.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Socket error codes.
+ *  Based on BSD.
+ */
+
+#ifndef __NET_SOCKET_ERR_H__
+#define __NET_SOCKET_ERR_H__
+
+#include <errno.h>
+
+/** @name Socket error codes definitions
+ */
+/*@{*/
+
+////#define EINTR			(-10004)
+////#define EBADF			(-10009)
+//#define EACCES			(-10013)
+//#define EFAULT			(-10014)
+////#define EINVAL			(-10022)
+////#define EMFILE			(-10024)
+//#define EWOULDBLOCK		(-10035)
+
+/** An API function is called while another blocking function is in progress.
+ */
+#define EINPROGRESS		(-10036)
+
+//#define EALREADY		(-10037)
+
+/** The socket identifier is not valid.
+ */
+#define ENOTSOCK		(-10038)
+
+/** The destination address required.
+ */
+#define EDESTADDRREQ	(-10039)
+
+//#define EMSGSIZE		(-10040)
+//#define EPROTOTYPE		(-10041)
+//#define ENOPROTOOPT		(-10042)
+
+/** Protocol is not supported.
+ */
+#define EPROTONOSUPPORT	(-10043)
+
+/** Socket type is not supported.
+ */
+#define ESOCKTNOSUPPORT	(-10044)
+
+//#define EOPNOTSUPP		(-10045)
+
+/** Protocol family is not supported.
+ */
+#define EPFNOSUPPORT	(-10046)
+
+/** Address family is not supported.
+ */
+#define EAFNOSUPPORT	(-10047)
+
+/** Address is already in use.
+ */
+#define EADDRINUSE		(-10048)
+
+//#define EADDRNOTAVAIL	(-10049)
+/* May be reported at any time if the implementation detects an underlying failure.
+ */
+//#define ENETDOWN		(-10050)
+//#define ENETUNREACH		(-10051)
+//#define ENETRESET		(-10052)
+//#define ECONNABORTED	(-10053)
+//#define ECONNRESET		(-10054)
+//#define ENOBUFS			(-10055)
+//#define EISCONN			(-10056)
+
+/** The socket is not connected or bound.
+ */
+#define ENOTCONN		(-10057)
+
+//#define ESHUTDOWN		(-10058)
+//#define ETOOMANYREFS	(-10059)
+//#define ETIMEDOUT		(-10060)
+//#define ECONNREFUSED	(-10061)
+//#define ELOOP			(-10062)
+////#define ENAMETOOLONG	(-10063)
+//#define EHOSTDOWN		(-10064)
+//#define EHOSTUNREACH	(-10065)
+//#define HOST_NOT_FOUND	(-11001)
+
+/** The requested operation was not performed.
+ *  Try again later.
+ */
+#define TRY_AGAIN		(-11002)
+
+//#define NO_RECOVERY		(-11003)
+
+/** No data.
+ */
+#define NO_DATA			(-11004)
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/usb/include/usb/devdrv.h
===================================================================
--- uspace/lib/usb/include/usb/devdrv.h	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/usb/include/usb/devdrv.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -169,4 +169,12 @@
     usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
 
+int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
+int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
+    usb_endpoint_description_t **, uint8_t *, size_t, int, int,
+    usb_endpoint_mapping_t **, size_t *);
+int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
+
+size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
+
 #endif
 /**
Index: uspace/lib/usb/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usb/include/usb/host/device_keeper.h	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/usb/include/usb/host/device_keeper.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -73,4 +73,6 @@
 void usb_device_keeper_add_ep(
     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
+void usb_device_keeper_del_ep(
+    usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
 
 void usb_device_keeper_reserve_default_address(
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/usb/include/usb/pipes.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -153,4 +153,6 @@
 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
     size_t, 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/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/usb/include/usb/usb.h	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -77,5 +77,7 @@
 	USB_SPEED_FULL,
 	/** USB 2.0 high speed (480Mbits/s). */
-	USB_SPEED_HIGH
+	USB_SPEED_HIGH,
+	/** Psuedo-speed serving as a boundary. */
+	USB_SPEED_MAX
 } usb_speed_t;
 
Index: uspace/lib/usb/src/devdrv.c
===================================================================
--- uspace/lib/usb/src/devdrv.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/usb/src/devdrv.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -72,14 +72,4 @@
 }
 
-/** Log out of memory error on given device.
- *
- * @param dev Device causing the trouble.
- */
-static void usb_log_oom(ddf_dev_t *dev)
-{
-	usb_log_error("Out of memory when adding device `%s'.\n",
-	    dev->name);
-}
-
 /** Count number of pipes the driver expects.
  *
@@ -108,93 +98,25 @@
  */
 static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
-    usb_device_t *dev)
-{
-	int rc;
-
-	size_t pipe_count = count_other_pipes(endpoints);
-	if (pipe_count == 0) {
-		return EOK;
-	}
-
-	dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
-	if (dev->pipes == NULL) {
-		usb_log_oom(dev->ddf_dev);
-		return ENOMEM;
-	}
-
-	size_t i;
-
-	/* Initialize to NULL first for rollback purposes. */
-	for (i = 0; i < pipe_count; i++) {
-		dev->pipes[i].pipe = NULL;
-	}
-
-	for (i = 0; i < pipe_count; i++) {
-		dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t));
-		if (dev->pipes[i].pipe == NULL) {
-			usb_log_oom(dev->ddf_dev);
-			rc = ENOMEM;
-			goto rollback;
-		}
-
-		dev->pipes[i].description = endpoints[i];
-		dev->pipes[i].interface_no = dev->interface_no;
-		dev->pipes[i].interface_setting = 0;
-	}
-
-	rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count,
+    usb_device_t *dev, int alternate_setting)
+{
+	usb_endpoint_mapping_t *pipes;
+	size_t pipes_count;
+
+	int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
 	    dev->descriptors.configuration, dev->descriptors.configuration_size,
-	    &dev->wire);
-	if (rc != EOK) {
-		usb_log_error("Failed initializing USB endpoints: %s.\n",
-		    str_error(rc));
-		goto rollback;
-	}
-
-	/* Register the endpoints. */
-	usb_hc_connection_t hc_conn;
-	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
+	    dev->interface_no, alternate_setting,
+	    &pipes, &pipes_count);
+
 	if (rc != EOK) {
 		usb_log_error(
-		    "Failed initializing connection to host controller: %s.\n",
-		    str_error(rc));
-		goto rollback;
-	}
-	rc = usb_hc_connection_open(&hc_conn);
-	if (rc != EOK) {
-		usb_log_error("Failed to connect to host controller: %s.\n",
-		    str_error(rc));
-		goto rollback;
-	}
-	for (i = 0; i < pipe_count; i++) {
-		if (dev->pipes[i].present) {
-			rc = usb_pipe_register(dev->pipes[i].pipe,
-			    dev->pipes[i].descriptor->poll_interval,
-			    &hc_conn);
-			/* Ignore error when operation not supported by HC. */
-			if ((rc != EOK) && (rc != ENOTSUP)) {
-				/* FIXME: what shall we do? */
-				dev->pipes[i].present = false;
-				free(dev->pipes[i].pipe);
-				dev->pipes[i].pipe = NULL;
-			}
-		}
-	}
-	/* Ignoring errors here. */
-	usb_hc_connection_close(&hc_conn);
-
-	dev->pipes_count = pipe_count;
+		    "Failed to create endpoint pipes for `%s': %s.\n",
+		    dev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	dev->pipes = pipes;
+	dev->pipes_count = pipes_count;
 
 	return EOK;
-
-rollback:
-	for (i = 0; i < pipe_count; i++) {
-		if (dev->pipes[i].pipe != NULL) {
-			free(dev->pipes[i].pipe);
-		}
-	}
-	free(dev->pipes);
-
-	return rc;
 }
 
@@ -249,27 +171,17 @@
 	}
 
-	/* Get the device descriptor. */
-	rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
-	    &dev->descriptors.device);
-	if (rc != EOK) {
-		usb_pipe_end_long_transfer(&dev->ctrl_pipe);
-		usb_log_error("Failed to retrieve device descriptor: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	/* Get the full configuration descriptor. */
-	rc = usb_request_get_full_configuration_descriptor_alloc(
-	    &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration,
-	    &dev->descriptors.configuration_size);
-	if (rc != EOK) {
-		usb_pipe_end_long_transfer(&dev->ctrl_pipe);
-		usb_log_error("Failed retrieving configuration descriptor: %s. %s\n",
+	/* Retrieve the descriptors. */
+	rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
+	    &dev->descriptors);
+	if (rc != EOK) {
+		usb_log_error("Failed to retrieve standard device " \
+		    "descriptors of %s: %s.\n",
 		    dev->ddf_dev->name, str_error(rc));
 		return rc;
 	}
 
+
 	if (driver->endpoints != NULL) {
-		rc = initialize_other_pipes(driver->endpoints, dev);
+		rc = initialize_other_pipes(driver->endpoints, dev, 0);
 	}
 
@@ -293,8 +205,10 @@
  * @return Number of alternate interfaces for @p interface_no interface.
  */
-static size_t count_alternate_interfaces(uint8_t *config_descr,
-    size_t config_descr_size, int interface_no)
+size_t usb_interface_count_alternates(uint8_t *config_descr,
+    size_t config_descr_size, uint8_t interface_no)
 {
 	assert(config_descr != NULL);
+	assert(config_descr_size > 0);
+
 	usb_dp_parser_t dp_parser = {
 		.nesting = usb_dp_standard_descriptor_nesting
@@ -345,5 +259,5 @@
 
 	alternates->alternative_count
-	    = count_alternate_interfaces(dev->descriptors.configuration,
+	    = usb_interface_count_alternates(dev->descriptors.configuration,
 	    dev->descriptors.configuration_size, dev->interface_no);
 
@@ -459,36 +373,10 @@
 static int destroy_current_pipes(usb_device_t *dev)
 {
-	size_t i;
-	int rc;
-
-	/* TODO: this shall be done under some device mutex. */
-
-	/* First check that no session is opened. */
-	for (i = 0; i < dev->pipes_count; i++) {
-		if (usb_pipe_is_session_started(dev->pipes[i].pipe)) {
-			return EBUSY;
-		}
-	}
-
-	/* Prepare connection to HC. */
-	usb_hc_connection_t hc_conn;
-	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
-	if (rc != EOK) {
-		return rc;
-	}
-	rc = usb_hc_connection_open(&hc_conn);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Destroy the pipes. */
-	for (i = 0; i < dev->pipes_count; i++) {
-		usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn);
-		free(dev->pipes[i].pipe);
-	}
-
-	usb_hc_connection_close(&hc_conn);
-
-	free(dev->pipes);
+	int rc = usb_device_destroy_pipes(dev->ddf_dev,
+	    dev->pipes, dev->pipes_count);
+	if (rc != EOK) {
+		return rc;
+	}
+
 	dev->pipes = NULL;
 	dev->pipes_count = 0;
@@ -537,7 +425,218 @@
 
 	/* Create new pipes. */
-	rc = initialize_other_pipes(endpoints, dev);
+	rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
 
 	return rc;
+}
+
+/** Retrieve basic descriptors from the device.
+ *
+ * @param[in] ctrl_pipe Control pipe with opened session.
+ * @param[out] descriptors Where to store the descriptors.
+ * @return Error code.
+ */
+int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe,
+    usb_device_descriptors_t *descriptors)
+{
+	assert(descriptors != NULL);
+	assert(usb_pipe_is_session_started(ctrl_pipe));
+
+	descriptors->configuration = NULL;
+
+	int rc;
+
+	/* Get the device descriptor. */
+	rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Get the full configuration descriptor. */
+	rc = usb_request_get_full_configuration_descriptor_alloc(
+	    ctrl_pipe, 0, (void **) &descriptors->configuration,
+	    &descriptors->configuration_size);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Create pipes for a device.
+ *
+ * This is more or less a wrapper that does following actions:
+ * - allocate and initialize pipes
+ * - map endpoints to the pipes based on the descriptions
+ * - registers endpoints with the host controller
+ *
+ * @param[in] dev Generic DDF device backing the USB one.
+ * @param[in] wire Initialized backing connection to the host controller.
+ * @param[in] endpoints Endpoints description, NULL terminated.
+ * @param[in] config_descr Configuration descriptor of active configuration.
+ * @param[in] config_descr_size Size of @p config_descr in bytes.
+ * @param[in] interface_no Interface to map from.
+ * @param[in] interface_setting Interface setting (default is usually 0).
+ * @param[out] pipes_ptr Where to store array of created pipes
+ *	(not NULL terminated).
+ * @param[out] pipes_count_ptr Where to store number of pipes
+ *	(set to if you wish to ignore the count).
+ * @return Error code.
+ */
+int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,
+    usb_endpoint_description_t **endpoints,
+    uint8_t *config_descr, size_t config_descr_size,
+    int interface_no, int interface_setting,
+    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
+{
+	assert(dev != NULL);
+	assert(wire != NULL);
+	assert(endpoints != NULL);
+	assert(config_descr != NULL);
+	assert(config_descr_size > 0);
+	assert(pipes_ptr != NULL);
+
+	size_t i;
+	int rc;
+
+	size_t pipe_count = count_other_pipes(endpoints);
+	if (pipe_count == 0) {
+		*pipes_ptr = NULL;
+		return EOK;
+	}
+
+	usb_endpoint_mapping_t *pipes
+	    = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
+	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;
+		pipes[i].interface_setting = interface_setting;
+	}
+
+	/* Find the mapping from configuration descriptor. */
+	rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
+	    config_descr, config_descr_size, wire);
+	if (rc != EOK) {
+		goto rollback_free_only;
+	}
+
+	/* Register the endpoints with HC. */
+	usb_hc_connection_t hc_conn;
+	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
+	if (rc != EOK) {
+		goto rollback_free_only;
+	}
+
+	rc = usb_hc_connection_open(&hc_conn);
+	if (rc != EOK) {
+		goto rollback_free_only;
+	}
+
+	for (i = 0; i < pipe_count; i++) {
+		if (pipes[i].present) {
+			rc = usb_pipe_register(pipes[i].pipe,
+			    pipes[i].descriptor->poll_interval, &hc_conn);
+			if (rc != EOK) {
+				goto rollback_unregister_endpoints;
+			}
+		}
+	}
+
+	usb_hc_connection_close(&hc_conn);
+
+	*pipes_ptr = pipes;
+	if (pipes_count_ptr != NULL) {
+		*pipes_count_ptr = pipe_count;
+	}
+
+	return EOK;
+
+	/*
+	 * Jump here if something went wrong after endpoints have
+	 * been registered.
+	 * This is also the target when the registration of
+	 * endpoints fails.
+	 */
+rollback_unregister_endpoints:
+	for (i = 0; i < pipe_count; i++) {
+		if (pipes[i].present) {
+			usb_pipe_unregister(pipes[i].pipe, &hc_conn);
+		}
+	}
+
+	usb_hc_connection_close(&hc_conn);
+
+	/*
+	 * Jump here if something went wrong before some actual communication
+	 * with HC. Then the only thing that needs to be done is to free
+	 * allocated memory.
+	 */
+rollback_free_only:
+	for (i = 0; i < pipe_count; i++) {
+		if (pipes[i].pipe != NULL) {
+			free(pipes[i].pipe);
+		}
+	}
+	free(pipes);
+
+	return rc;
+}
+
+/** Destroy pipes previously created by usb_device_create_pipes.
+ *
+ * @param[in] dev Generic DDF device backing the USB one.
+ * @param[in] pipes Endpoint mapping to be destroyed.
+ * @param[in] pipes_count Number of endpoints.
+ */
+int usb_device_destroy_pipes(ddf_dev_t *dev,
+    usb_endpoint_mapping_t *pipes, size_t pipes_count)
+{
+	assert(dev != NULL);
+	assert(((pipes != NULL) && (pipes_count > 0))
+	    || ((pipes == NULL) && (pipes_count == 0)));
+
+	if (pipes_count == 0) {
+		return EOK;
+	}
+
+	int rc;
+
+	/* Prepare connection to HC to allow endpoint unregistering. */
+	usb_hc_connection_t hc_conn;
+	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = usb_hc_connection_open(&hc_conn);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Destroy the pipes. */
+	size_t i;
+	for (i = 0; i < pipes_count; i++) {
+		usb_pipe_unregister(pipes[i].pipe, &hc_conn);
+		free(pipes[i].pipe);
+	}
+
+	usb_hc_connection_close(&hc_conn);
+
+	free(pipes);
+
+	return EOK;
 }
 
Index: uspace/lib/usb/src/host/device_keeper.c
===================================================================
--- uspace/lib/usb/src/host/device_keeper.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/usb/src/host/device_keeper.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -56,6 +56,10 @@
 		instance->devices[i].control_used = 0;
 		instance->devices[i].handle = 0;
+		instance->devices[i].speed = USB_SPEED_MAX;
 		list_initialize(&instance->devices[i].endpoints);
 	}
+	// TODO: is this hack enough?
+	// (it is needed to allow smooth registration at default address)
+	instance->devices[0].occupied = true;
 }
 /*----------------------------------------------------------------------------*/
@@ -67,4 +71,15 @@
 	assert(instance->devices[address].occupied);
 	list_append(&ep->same_device_eps, &instance->devices[address].endpoints);
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+void usb_device_keeper_del_ep(
+    usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	assert(instance->devices[address].occupied);
+	list_remove(&ep->same_device_eps);
+	list_initialize(&ep->same_device_eps);
 	fibril_mutex_unlock(&instance->guard);
 }
Index: uspace/lib/usb/src/hub.c
===================================================================
--- uspace/lib/usb/src/hub.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/usb/src/hub.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -40,4 +40,5 @@
 #include <errno.h>
 #include <assert.h>
+#include <usb/debug.h>
 
 /** Check that HC connection is alright.
@@ -55,4 +56,5 @@
 
 /** Tell host controller to reserve default address.
+ * @deprecated
  *
  * @param connection Opened connection to host controller.
@@ -65,4 +67,6 @@
 	CHECK_CONNECTION(connection);
 
+	usb_log_warning("usb_hc_reserve_default_address() considered obsolete");
+
 	return async_req_2_0(connection->hc_phone,
 	    DEV_IFACE_ID(USBHC_DEV_IFACE),
@@ -71,4 +75,5 @@
 
 /** Tell host controller to release default address.
+ * @deprecated
  *
  * @param connection Opened connection to host controller.
@@ -78,4 +83,6 @@
 {
 	CHECK_CONNECTION(connection);
+
+	usb_log_warning("usb_hc_release_default_address() considered obsolete");
 
 	return async_req_1_0(connection->hc_phone,
@@ -235,25 +242,9 @@
 	}
 
-
-	/*
-	 * Reserve the default address.
-	 */
-	rc = usb_hc_reserve_default_address(&hc_conn, dev_speed);
-	if (rc != EOK) {
-		rc = EBUSY;
-		goto leave_release_free_address;
-	}
-
-	/*
-	 * Enable the port (i.e. allow signaling through this port).
-	 */
-	rc = enable_port(port_no, arg);
-	if (rc != EOK) {
-		goto leave_release_default_address;
-	}
-
-	/*
-	 * Change the address from default to the free one.
-	 * We need to create a new control pipe for that.
+	/*
+	 * We will not register control pipe on default address.
+	 * The registration might fail. That means that someone else already
+	 * registered that endpoint. We will simply wait and try again.
+	 * (Someone else already wants to add a new device.)
 	 */
 	usb_device_connection_t dev_conn;
@@ -262,5 +253,5 @@
 	if (rc != EOK) {
 		rc = ENOTCONN;
-		goto leave_release_default_address;
+		goto leave_release_free_address;
 	}
 
@@ -270,46 +261,50 @@
 	if (rc != EOK) {
 		rc = ENOTCONN;
+		goto leave_release_free_address;
+	}
+
+	do {
+		rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
+		    &hc_conn);
+		if (rc != EOK) {
+			/* Do not overheat the CPU ;-). */
+			async_usleep(10);
+		}
+	} while (rc != EOK);
+
+	/*
+	 * Endpoint is registered. We can enable the port and change
+	 * device address.
+	 */
+	rc = enable_port(port_no, arg);
+	if (rc != EOK) {
 		goto leave_release_default_address;
 	}
 
-	/* Before sending any traffic, we need to register this
-	 * endpoint.
+	rc = usb_pipe_probe_default_control(&ctrl_pipe);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_release_default_address;
+	}
+
+	rc = usb_request_set_address(&ctrl_pipe, dev_addr);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_release_default_address;
+	}
+
+	/*
+	 * 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) {
-		rc = EREFUSED;
-		goto leave_release_default_address;
-	}
-	rc = usb_pipe_probe_default_control(&ctrl_pipe);
-	if (rc != EOK) {
-		rc = ENOTCONN;
-		goto leave_release_default_address;
-	}
-
-	rc = usb_request_set_address(&ctrl_pipe, dev_addr);
-	if (rc != EOK) {
-		rc = ESTALL;
-		goto leave_stop_session;
-	}
-
-	/*
-	 * Register the control endpoint for the new device.
-	 */
-	rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
-	if (rc != EOK) {
-		rc = EREFUSED;
-		goto leave_unregister_endpoint;
-	}
-
-	/*
-	 * Release the original endpoint.
-	 */
-	unregister_control_endpoint_on_default_address(&hc_conn);
-
-	/*
-	 * Once the address is changed, we can return the default address.
-	 */
-	usb_hc_release_default_address(&hc_conn);
-
+		goto leave_release_free_address;
+	}
 
 	/*
@@ -326,6 +321,4 @@
 	}
 
-
-
 	/*
 	 * And now inform the host controller about the handle.
@@ -359,13 +352,6 @@
 	 * Completely ignoring errors here.
 	 */
-
-leave_stop_session:
-	usb_pipe_end_session(&ctrl_pipe);
-
-leave_unregister_endpoint:
+leave_release_default_address:
 	usb_pipe_unregister(&ctrl_pipe, &hc_conn);
-
-leave_release_default_address:
-	usb_hc_release_default_address(&hc_conn);
 
 leave_release_free_address:
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision 7b71589214d277bc89e2dc6a413210eead6776df)
+++ uspace/lib/usb/src/pipesinit.c	(revision c6394aab5f25d8aa4ee43579066a790a983ee510)
@@ -459,4 +459,25 @@
     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,
+    usb_hc_connection_t *hc_connection)
+{
 	assert(pipe);
 	assert(hc_connection);
@@ -466,13 +487,15 @@
 	}
 
-#define _PACK(high, low) ((high) * 256 + (low))
-
-	return async_req_5_0(hc_connection->hc_phone,
+#define _PACK2(high, low) (((high) << 16) + (low))
+#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
+
+	return async_req_4_0(hc_connection->hc_phone,
 	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
-	    _PACK(pipe->wire->address, pipe->endpoint_no),
-	    _PACK(pipe->transfer_type, pipe->direction),
-	    pipe->max_packet_size, interval);
-
-#undef _PACK
+	    _PACK2(pipe->wire->address, pipe->endpoint_no),
+	    _PACK3(speed, pipe->transfer_type, pipe->direction),
+	    _PACK2(pipe->max_packet_size, interval));
+
+#undef _PACK2
+#undef _PACK3
 }
 
