Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/app/tester/Makefile	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -31,6 +31,10 @@
 BINARY = tester
 
+LIBS += $(LIBUSB_PREFIX)/libusb.a
+EXTRA_CFLAGS += -I$(LIBUSB_PREFIX)/include
+
 SOURCES = \
 	tester.c \
+	adt/usbaddrkeep.c \
 	thread/thread1.c \
 	print/print1.c \
Index: uspace/app/tester/adt/usbaddrkeep.c
===================================================================
--- uspace/app/tester/adt/usbaddrkeep.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/app/tester/adt/usbaddrkeep.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <usb/hcd.h>
+#include <errno.h>
+#include "../tester.h"
+
+#define MAX_ADDRESS 5
+
+
+const char *test_usbaddrkeep(void)
+{
+	int rc;
+	usb_address_keeping_t addresses;
+
+	TPRINTF("Initializing addresses keeping structure...\n");
+	usb_address_keeping_init(&addresses, MAX_ADDRESS);
+	
+	TPRINTF("Requesting address...\n");
+	usb_address_t addr = usb_address_keeping_request(&addresses);
+	TPRINTF("Address assigned: %d\n", (int) addr);
+	if (addr != 1) {
+		return "have not received expected address 1";
+	}
+
+	TPRINTF("Releasing not assigned address...\n");
+	rc = usb_address_keeping_release(&addresses, 2);
+	if (rc != ENOENT) {
+		return "have not received expected ENOENT";
+	}
+
+	TPRINTF("Releasing acquired address...\n");
+	rc = usb_address_keeping_release(&addresses, addr);
+	if (rc != EOK) {
+		return "have not received expected EOK";
+	}
+
+	return NULL;
+}
Index: uspace/app/tester/adt/usbaddrkeep.def
===================================================================
--- uspace/app/tester/adt/usbaddrkeep.def	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/app/tester/adt/usbaddrkeep.def	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -0,0 +1,6 @@
+{
+	"usbaddrkeep",
+	"USB address keeping structure",
+	&test_usbaddrkeep,
+	true
+},
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/app/tester/tester.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -65,4 +65,5 @@
 #include "mm/malloc1.def"
 #include "hw/serial/serial1.def"
+#include "adt/usbaddrkeep.def"
 	{NULL, NULL, NULL, false}
 };
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/app/tester/tester.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -82,4 +82,5 @@
 extern const char *test_malloc1(void);
 extern const char *test_serial1(void);
+extern const char *test_usbaddrkeep(void);
 
 extern test_t tests[];
Index: uspace/drv/vhc/Makefile
===================================================================
--- uspace/drv/vhc/Makefile	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/drv/vhc/Makefile	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -39,5 +39,4 @@
 
 SOURCES = \
-	addrmgm.c \
 	conndev.c \
 	connhost.c \
Index: pace/drv/vhc/addrmgm.c
===================================================================
--- uspace/drv/vhc/addrmgm.c	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ 	(revision )
@@ -1,199 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup usb
- * @{
- */
-/** @file
- * @brief Address management.
- */
-
-#include <usb/usb.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <fibril_synch.h>
-
-#include "vhcd.h"
-#include "conn.h"
-
-#define ADDRESS_COUNT 100
-#define DEFAULT_ADDRESS 0
-
-typedef struct {
-	usb_address_t address;
-	devman_handle_t devman_handle;
-	bool available;
-} address_info_t;
-
-static address_info_t dev_address[ADDRESS_COUNT];
-fibril_mutex_t address_guard;
-
-typedef struct {
-	fibril_mutex_t condvar_guard;
-	fibril_condvar_t condvar;
-	bool available;
-} reservable_address_info_t;
-
-static reservable_address_info_t default_address;
-
-void address_init(void)
-{
-	usb_address_t i;
-	for (i = 0; i < ADDRESS_COUNT; i++) {
-		dev_address[i].address = i + 1;
-		dev_address[i].available = true;
-		dev_address[i].devman_handle = 0;
-	}
-
-	fibril_mutex_initialize(&address_guard);
-	fibril_mutex_initialize(&default_address.condvar_guard);
-	fibril_condvar_initialize(&default_address.condvar);
-}
-
-int reserve_default_address(device_t *dev)
-{
-	fibril_mutex_lock(&default_address.condvar_guard);
-	while (!default_address.available) {
-		fibril_condvar_wait(&default_address.condvar,
-		    &default_address.condvar_guard);
-	}
-	fibril_mutex_unlock(&default_address.condvar_guard);
-
-	return EOK;
-}
-
-int release_default_address(device_t *dev)
-{
-	fibril_mutex_lock(&default_address.condvar_guard);
-	default_address.available = true;
-	fibril_condvar_signal(&default_address.condvar);
-	fibril_mutex_unlock(&default_address.condvar_guard);
-
-	return EOK;
-}
-
-int request_address(device_t *dev, usb_address_t *address)
-{
-	fibril_mutex_lock(&address_guard);
-	usb_address_t i;
-	bool found = false;
-	for (i = 0; i < ADDRESS_COUNT; i++) {
-		if (dev_address[i].available) {
-			dev_address[i].available = false;
-			*address = dev_address[i].address;
-			found = true;
-			break;
-		}
-	}
-	fibril_mutex_unlock(&address_guard);
-
-	if (!found) {
-		return ELIMIT;
-	} else {
-		return EOK;
-	}
-}
-
-int bind_address(device_t *dev, usb_address_t address, devman_handle_t handle)
-{
-	if (address == DEFAULT_ADDRESS) {
-		return EPERM;
-	}
-
-	int rc = EPERM;
-
-	fibril_mutex_lock(&address_guard);
-	usb_address_t i;
-	for (i = 0; i < ADDRESS_COUNT; i++) {
-		if (dev_address[i].address == address) {
-			if (dev_address[i].available) {
-				rc = ENOENT;
-				break;
-			}
-
-			dev_address[i].devman_handle = handle;
-			rc = EOK;
-			break;
-		}
-	}
-	fibril_mutex_unlock(&address_guard);
-
-	return rc;
-}
-
-int tell_address(device_t *dev, devman_handle_t handle, usb_address_t *address)
-{
-	int rc = ENOENT;
-
-	fibril_mutex_lock(&address_guard);
-	usb_address_t i;
-	for (i = 0; i < ADDRESS_COUNT; i++) {
-		if (dev_address[i].devman_handle == handle) {
-			*address = dev_address[i].address;
-			rc = EOK;
-			break;
-		}
-	}
-	fibril_mutex_unlock(&address_guard);
-
-	return rc;
-}
-
-int release_address(device_t *dev, usb_address_t address)
-{
-	if (address == DEFAULT_ADDRESS) {
-		return EPERM;
-	}
-
-	int rc = EPERM;
-
-	fibril_mutex_lock(&address_guard);
-	usb_address_t i;
-	for (i = 0; i < ADDRESS_COUNT; i++) {
-		if (dev_address[i].address == address) {
-			if (dev_address[i].available) {
-				rc = ENOENT;
-				break;
-			}
-
-			dev_address[i].available = true;
-			dev_address[i].devman_handle = 0;
-			rc = EOK;
-			break;
-		}
-	}
-	fibril_mutex_unlock(&address_guard);
-
-	return rc;
-}
-
-/**
- * @}
- */
Index: uspace/drv/vhc/conn.h
===================================================================
--- uspace/drv/vhc/conn.h	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/drv/vhc/conn.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -48,11 +48,5 @@
 
 void address_init(void);
-int reserve_default_address(device_t *);
-int release_default_address(device_t *);
-int request_address(device_t *, usb_address_t *);
-int release_address(device_t *, usb_address_t);
-int bind_address(device_t *, usb_address_t, devman_handle_t);
 
-int tell_address(device_t *, devman_handle_t, usb_address_t *);
 
 void default_connection_handler(device_t *, ipc_callid_t, ipc_call_t *);
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/drv/vhc/connhost.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -36,4 +36,5 @@
 #include <errno.h>
 #include <usb/usb.h>
+#include <usb/hcd.h>
 
 #include "vhcd.h"
@@ -218,4 +219,58 @@
 }
 
+static usb_address_keeping_t addresses;
+
+
+static int reserve_default_address(device_t *dev)
+{
+	usb_address_keeping_reserve_default(&addresses);
+	return EOK;
+}
+
+static int release_default_address(device_t *dev)
+{
+	usb_address_keeping_release_default(&addresses);
+	return EOK;
+}
+
+static int request_address(device_t *dev, usb_address_t *address)
+{
+	usb_address_t addr = usb_address_keeping_request(&addresses);
+	if (addr < 0) {
+		return (int)addr;
+	}
+
+	*address = addr;
+	return EOK;
+}
+
+static int release_address(device_t *dev, usb_address_t address)
+{
+	return usb_address_keeping_release(&addresses, address);
+}
+
+static int bind_address(device_t *dev, usb_address_t address,
+    devman_handle_t handle)
+{
+	usb_address_keeping_devman_bind(&addresses, address, handle);
+	return EOK;
+}
+
+static int tell_address(device_t *dev, devman_handle_t handle,
+    usb_address_t *address)
+{
+	usb_address_t addr = usb_address_keeping_find(&addresses, handle);
+	if (addr < 0) {
+		return addr;
+	}
+
+	*address = addr;
+	return EOK;
+}
+
+void address_init(void)
+{
+	usb_address_keeping_init(&addresses, 50);
+}
 
 usbhc_iface_t vhc_iface = {
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/lib/usb/Makefile	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -33,4 +33,5 @@
 
 SOURCES = \
+	src/addrkeep.c \
 	src/hcdhubd.c \
 	src/hcdrv.c \
@@ -38,4 +39,5 @@
 	src/remotedrv.c \
 	src/usb.c \
+	src/usbdrvreq.c \
 	src/usbdrv.c
 
Index: uspace/lib/usb/include/usb/hcd.h
===================================================================
--- uspace/lib/usb/include/usb/hcd.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/usb/include/usb/hcd.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb usb
+ * @{
+ */
+/** @file
+ * @brief HC driver.
+ */
+#ifndef LIBUSB_HCD_H_
+#define LIBUSB_HCD_H_
+
+#include <usb/usb.h>
+#include <fibril_synch.h>
+#include <devman.h>
+
+/** Info about used address. */
+typedef struct {
+	/** Linked list member. */
+	link_t link;
+	/** Address. */
+	usb_address_t address;
+	/** Corresponding devman handle. */
+	devman_handle_t devman_handle;
+} usb_address_keeping_used_t;
+
+/** Structure for keeping track of free and used USB addresses. */
+typedef struct {
+	/** Head of list of used addresses. */
+	link_t used_addresses;
+	/** Upper bound for USB addresses. */
+	usb_address_t max_address;
+	/** Mutex protecting used address. */
+	fibril_mutex_t used_addresses_guard;
+	/** Condition variable for used addresses. */
+	fibril_condvar_t used_addresses_condvar;
+
+	/** Condition variable mutex for default address. */
+	fibril_mutex_t default_condvar_guard;
+	/** Condition variable for default address. */
+	fibril_condvar_t default_condvar;
+	/** Whether is default address available. */
+	bool default_available;
+} usb_address_keeping_t;
+
+void usb_address_keeping_init(usb_address_keeping_t *, usb_address_t);
+
+void usb_address_keeping_reserve_default(usb_address_keeping_t *);
+void usb_address_keeping_release_default(usb_address_keeping_t *);
+
+usb_address_t usb_address_keeping_request(usb_address_keeping_t *);
+int usb_address_keeping_release(usb_address_keeping_t *, usb_address_t);
+void usb_address_keeping_devman_bind(usb_address_keeping_t *, usb_address_t,
+    devman_handle_t);
+usb_address_t usb_address_keeping_find(usb_address_keeping_t *,
+    devman_handle_t);
+
+
+#endif
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/lib/usb/include/usb/usb.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -69,4 +69,7 @@
 typedef int usb_address_t;
 
+/** Default USB address. */
+#define USB_ADDRESS_DEFAULT 0
+
 /** USB endpoint number type.
  * Negative values could be used to indicate error.
Index: uspace/lib/usb/include/usb/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
+++ uspace/lib/usb/include/usb/usbdrv.h	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -36,5 +36,5 @@
 #define LIBUSB_USBDRV_H_
 
-#include "usb.h"
+#include <usb/usb.h>
 #include <driver.h>
 
@@ -70,4 +70,7 @@
 int usb_drv_async_wait_for(usb_handle_t);
 
+
+int usb_drv_req_set_address(int, usb_address_t, usb_address_t);
+
 #endif
 /**
Index: uspace/lib/usb/src/addrkeep.c
===================================================================
--- uspace/lib/usb/src/addrkeep.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/usb/src/addrkeep.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb usb
+ * @{
+ */
+/** @file
+ * @brief Address keeping.
+ */
+#include <usb/hcd.h>
+#include <errno.h>
+#include <assert.h>
+
+/** For loop over all used addresses in address keeping.
+ *
+ * @param link Iterator.
+ * @param addresses Addresses keeping structure to iterate.
+ */
+#define for_all_used_addresses(link, addresses) \
+	for (link = (addresses)->used_addresses.next; \
+	    link != &(addresses)->used_addresses; \
+	    link = link->next)
+
+/** Get instance of usb_address_keeping_used_t. */
+#define used_address_get_instance(lnk) \
+	list_get_instance(lnk, usb_address_keeping_used_t, link)
+
+/** Invalid value of devman handle. */
+#define INVALID_DEVMAN_HANDLE \
+	((devman_handle_t)-1)
+
+/** Creates structure for used USB address.
+ *
+ * @param address USB address.
+ * @return Initialized structure.
+ * @retval NULL Out of memory.
+ */
+static usb_address_keeping_used_t *usb_address_keeping_used_create(
+    usb_address_t address)
+{
+	usb_address_keeping_used_t *info
+	    = malloc(sizeof(usb_address_keeping_used_t));
+	if (info == NULL) {
+		return NULL;
+	}
+
+	info->address = address;
+	info->devman_handle = INVALID_DEVMAN_HANDLE;
+	list_initialize(&info->link);
+	return info;
+}
+
+/** Destroys structure for used USB address.
+ *
+ * @param info Structure to be destroyed.
+ */
+static void usb_address_keeping_used_destroy(usb_address_keeping_used_t *info)
+{
+	free(info);
+}
+
+/** Find used USB address structure by USB address.
+ *
+ * It is expected that guard mutex is already locked.
+ *
+ * @param addresses Address keeping info.
+ * @param address Address to be found.
+ * @return Structure describing looked for address.
+ * @retval NULL Address not found.
+ */
+static usb_address_keeping_used_t *usb_address_keeping_used_find_no_lock(
+    usb_address_keeping_t *addresses, usb_address_t address)
+{
+	link_t *link;
+	for_all_used_addresses(link, addresses) {
+		usb_address_keeping_used_t *info
+		    = used_address_get_instance(link);
+
+		if (info->address == address) {
+			return info;
+		}
+	}
+
+	return NULL;
+}
+
+/** Initialize address keeping structure.
+ *
+ * @param addresses Address keeping info.
+ * @param max_address Maximum USB address (exclusive bound).
+ */
+void usb_address_keeping_init(usb_address_keeping_t *addresses,
+    usb_address_t max_address)
+{
+	/*
+	 * Items related with used addresses.
+	 */
+	addresses->max_address = max_address;
+	list_initialize(&addresses->used_addresses);
+	fibril_mutex_initialize(&addresses->used_addresses_guard);
+	fibril_condvar_initialize(&addresses->used_addresses_condvar);
+
+	/*
+	 * Items related with default address.
+	 */
+	addresses->default_available = true;
+	fibril_condvar_initialize(&addresses->default_condvar);
+	fibril_mutex_initialize(&addresses->default_condvar_guard);
+}
+
+/** Reserved default USB address.
+ *
+ * This function blocks until reserved address is available.
+ *
+ * @see usb_address_keeping_release_default
+ *
+ * @param addresses Address keeping info.
+ */
+void usb_address_keeping_reserve_default(usb_address_keeping_t *addresses)
+{
+	fibril_mutex_lock(&addresses->default_condvar_guard);
+	while (!addresses->default_available) {
+		fibril_condvar_wait(&addresses->default_condvar,
+			&addresses->default_condvar_guard);
+	}
+	fibril_mutex_unlock(&addresses->default_condvar_guard);
+}
+
+/** Releases default USB address.
+ *
+ * @see usb_address_keeping_reserve_default
+ *
+ * @param addresses Address keeping info.
+ */
+void usb_address_keeping_release_default(usb_address_keeping_t *addresses)
+{
+	fibril_mutex_lock(&addresses->default_condvar_guard);
+	addresses->default_available = true;
+	fibril_condvar_signal(&addresses->default_condvar);
+	fibril_mutex_unlock(&addresses->default_condvar_guard);
+}
+
+/** Request free address assignment.
+ *
+ * This function does not block when there are not free addresses to be
+ * assigned.
+ *
+ * @param addresses Address keeping info.
+ * @return USB address that could be used or negative error code.
+ * @retval ELIMIT No more addresses to assign.
+ * @retval ENOMEM Out of memory.
+ */
+usb_address_t usb_address_keeping_request(usb_address_keeping_t *addresses)
+{
+	usb_address_t previous_address = 0;
+	usb_address_t free_address = 0;
+
+	fibril_mutex_lock(&addresses->used_addresses_guard);
+	link_t *new_address_position;
+	if (list_empty(&addresses->used_addresses)) {
+		free_address = 1;
+		new_address_position = addresses->used_addresses.next;
+	} else {
+		for_all_used_addresses(new_address_position, addresses) {
+			usb_address_keeping_used_t *info
+			    = used_address_get_instance(new_address_position);
+			if (info->address > previous_address + 1) {
+				free_address = previous_address + 1;
+				break;
+			}
+		}
+
+		if (free_address == 0) {
+			usb_address_keeping_used_t *last
+			    = used_address_get_instance(addresses->used_addresses.next);
+			free_address = last->address;
+		}
+	}
+
+	if (free_address >= addresses->max_address) {
+		free_address = ELIMIT;
+		goto leave;
+	}
+
+	usb_address_keeping_used_t *used
+	    = usb_address_keeping_used_create(free_address);
+	if (used == NULL) {
+		free_address = ENOMEM;
+		goto leave;
+	}
+
+	list_prepend(&used->link, new_address_position);
+
+leave:
+	fibril_mutex_unlock(&addresses->used_addresses_guard);
+
+	return free_address;
+}
+
+/** Release USB address.
+ *
+ * @param addresses Address keeping info.
+ * @param address Address to be released.
+ * @return Error code.
+ * @retval ENOENT Address is not in use.
+ */
+int usb_address_keeping_release(usb_address_keeping_t *addresses,
+    usb_address_t address)
+{
+	int rc = ENOENT;
+
+	fibril_mutex_lock(&addresses->used_addresses_guard);
+
+	usb_address_keeping_used_t *info
+	    = usb_address_keeping_used_find_no_lock(addresses, address);
+
+	if (info != NULL) {
+		rc = EOK;
+		list_remove(&info->link);
+		usb_address_keeping_used_destroy(info);
+	}
+
+	fibril_mutex_unlock(&addresses->used_addresses_guard);
+
+	return rc;
+}
+
+/** Bind devman handle with USB address.
+ *
+ * When the @p address is invalid (e.g. no such entry), the request
+ * is silently ignored.
+ *
+ * @param addresses Address keeping info.
+ * @param address USB address.
+ * @param handle Devman handle.
+ */
+void usb_address_keeping_devman_bind(usb_address_keeping_t *addresses,
+    usb_address_t address, devman_handle_t handle)
+{
+	fibril_mutex_lock(&addresses->used_addresses_guard);
+
+	usb_address_keeping_used_t *info
+	    = usb_address_keeping_used_find_no_lock(addresses, address);
+	if (info == NULL) {
+		goto leave;
+	}
+
+	assert(info->address == address);
+	info->devman_handle = handle;
+
+	/*
+	 * Inform that new handle was added.
+	 */
+	fibril_condvar_broadcast(&addresses->used_addresses_condvar);
+
+leave:
+	fibril_mutex_unlock(&addresses->used_addresses_guard);
+}
+
+/** Find address by its devman handle.
+ *
+ * @param addresses Address keeping info.
+ * @param handle Devman handle.
+ * @return USB address or negative error code.
+ * @retval ENOENT No such address.
+ */
+static usb_address_t usb_address_keeping_find_no_lock(
+    usb_address_keeping_t *addresses, devman_handle_t handle)
+{
+	usb_address_t address = ENOENT;
+
+	link_t *link;
+	for_all_used_addresses(link, addresses) {
+		usb_address_keeping_used_t *info
+		    = used_address_get_instance(link);
+
+		if (info->devman_handle == handle) {
+			address = info->address;
+			break;
+		}
+	}
+
+	return address;
+}
+
+/** Find USB address by its devman handle.
+ *
+ * This function blocks until corresponding address is found.
+ *
+ * @param addresses Address keeping info.
+ * @param handle Devman handle.
+ * @return USB address or negative error code.
+ */
+usb_address_t usb_address_keeping_find(usb_address_keeping_t *addresses,
+    devman_handle_t handle)
+{
+	usb_address_t address = ENOENT;
+
+	fibril_mutex_lock(&addresses->used_addresses_guard);
+	while (true) {
+		address = usb_address_keeping_find_no_lock(addresses, handle);
+		if (address != ENOENT) {
+			break;
+		}
+		fibril_condvar_wait(&addresses->used_addresses_condvar,
+		    &addresses->used_addresses_guard);
+	}
+
+	fibril_mutex_unlock(&addresses->used_addresses_guard);
+
+	return address;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/usbdrvreq.c
===================================================================
--- uspace/lib/usb/src/usbdrvreq.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
+++ uspace/lib/usb/src/usbdrvreq.c	(revision aca85e4754944cd51f92c12db81a0d124f4fb191)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb usb
+ * @{
+ */
+/** @file
+ * @brief USB driver - standard USB requests (implementation).
+ */
+#include <usb/usbdrv.h>
+#include <usb/devreq.h>
+#include <errno.h>
+
+/** Change address of connected device.
+ *
+ * @see usb_drv_reserve_default_address
+ * @see usb_drv_release_default_address
+ * @see usb_drv_request_address
+ * @see usb_drv_release_address
+ * @see usb_drv_bind_address
+ *
+ * @param phone Open phone to HC driver.
+ * @param old_address Current address.
+ * @param address Address to be set.
+ * @return Error code.
+ */
+int usb_drv_req_set_address(int phone, usb_address_t old_address,
+    usb_address_t new_address)
+{
+	/* Prepare the target. */
+	usb_target_t target = {
+		.address = old_address,
+		.endpoint = 0
+	};
+
+	/* Prepare the setup packet. */
+	usb_device_request_setup_packet_t setup_packet = {
+		.request_type = 0,
+		.request = USB_DEVREQ_SET_ADDRESS,
+		.index = 0,
+		.length = 0,
+	};
+	setup_packet.value = new_address;
+
+	usb_handle_t handle;
+	int rc;
+
+	/* Start the control write transfer. */
+	rc = usb_drv_async_control_write_setup(phone, target,
+	    &setup_packet, sizeof(setup_packet), &handle);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = usb_drv_async_wait_for(handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Finish the control write transfer. */
+	rc = usb_drv_async_control_write_status(phone, target, &handle);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = usb_drv_async_wait_for(handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
