Index: uspace/drv/uhci-hcd/Makefile
===================================================================
--- uspace/drv/uhci-hcd/Makefile	(revision e7bc999ad582830200c9cdebcd975dc5ed9cc969)
+++ uspace/drv/uhci-hcd/Makefile	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
@@ -40,5 +40,4 @@
 	uhci_rh.c \
 	uhci_struct/transfer_descriptor.c \
-	utils/device_keeper.c \
 	pci.c \
 	batch.c
Index: uspace/drv/uhci-hcd/batch.h
===================================================================
--- uspace/drv/uhci-hcd/batch.h	(revision e7bc999ad582830200c9cdebcd975dc5ed9cc969)
+++ uspace/drv/uhci-hcd/batch.h	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
@@ -39,8 +39,8 @@
 #include <usbhc_iface.h>
 #include <usb/usb.h>
+#include <usb/host/device_keeper.h>
 
 #include "uhci_struct/transfer_descriptor.h"
 #include "uhci_struct/queue_head.h"
-#include "utils/device_keeper.h"
 
 typedef struct batch
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision e7bc999ad582830200c9cdebcd975dc5ed9cc969)
+++ uspace/drv/uhci-hcd/iface.c	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
@@ -41,5 +41,4 @@
 #include "iface.h"
 #include "uhci_hc.h"
-#include "utils/device_keeper.h"
 
 /** Reserve default address interface function
Index: uspace/drv/uhci-hcd/uhci_hc.h
===================================================================
--- uspace/drv/uhci-hcd/uhci_hc.h	(revision e7bc999ad582830200c9cdebcd975dc5ed9cc969)
+++ uspace/drv/uhci-hcd/uhci_hc.h	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
@@ -42,8 +42,8 @@
 
 #include <usbhc_iface.h>
+#include <usb/host/device_keeper.h>
 
 #include "batch.h"
 #include "transfer_list.h"
-#include "utils/device_keeper.h"
 
 typedef struct uhci_regs {
Index: pace/drv/uhci-hcd/utils/device_keeper.c
===================================================================
--- uspace/drv/uhci-hcd/utils/device_keeper.c	(revision e7bc999ad582830200c9cdebcd975dc5ed9cc969)
+++ 	(revision )
@@ -1,298 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * 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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#include <assert.h>
-#include <errno.h>
-#include <usb/debug.h>
-
-#include "device_keeper.h"
-
-/*----------------------------------------------------------------------------*/
-/** Initialize device keeper structure.
- *
- * @param[in] instance Memory place to initialize.
- *
- * Set all values to false/0.
- */
-void device_keeper_init(device_keeper_t *instance)
-{
-	assert(instance);
-	fibril_mutex_initialize(&instance->guard);
-	fibril_condvar_initialize(&instance->default_address_occupied);
-	instance->last_address = 0;
-	unsigned i = 0;
-	for (; i < USB_ADDRESS_COUNT; ++i) {
-		instance->devices[i].occupied = false;
-		instance->devices[i].handle = 0;
-		instance->devices[i].toggle_status = 0;
-	}
-}
-/*----------------------------------------------------------------------------*/
-/** Attempt to obtain address 0, blocks.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] speed Speed of the device requesting default address.
- */
-void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
-		fibril_condvar_wait(&instance->default_address_occupied,
-		    &instance->guard);
-	}
-	instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
-	instance->devices[USB_ADDRESS_DEFAULT].speed = speed;
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Attempt to obtain address 0, blocks.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] speed Speed of the device requesting default address.
- */
-void device_keeper_release_default(device_keeper_t *instance)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
-	fibril_mutex_unlock(&instance->guard);
-	fibril_condvar_signal(&instance->default_address_occupied);
-}
-/*----------------------------------------------------------------------------*/
-/** Check setup packet data for signs of toggle reset.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] target Device to receive setup packet.
- * @param[in] data Setup packet data.
- *
- * Really ugly one.
- */
-void device_keeper_reset_if_need(
-    device_keeper_t *instance, usb_target_t target, const unsigned char *data)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	if (target.endpoint > 15 || target.endpoint < 0
-	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
-	    || !instance->devices[target.address].occupied) {
-		fibril_mutex_unlock(&instance->guard);
-		usb_log_error("Invalid data when checking for toggle reset.\n");
-		return;
-	}
-
-	switch (data[1])
-	{
-	case 0x01: /*clear feature*/
-		/* recipient is endpoint, value is zero (ENDPOINT_STALL) */
-		if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
-			/* endpoint number is < 16, thus first byte is enough */
-			instance->devices[target.address].toggle_status &=
-			    ~(1 << data[4]);
-		}
-	break;
-
-	case 0x9: /* set configuration */
-	case 0x11: /* set interface */
-		/* target must be device */
-		if ((data[0] & 0xf) == 0) {
-			instance->devices[target.address].toggle_status = 0;
-		}
-	break;
-	}
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Get current value of endpoint toggle.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] target Device and endpoint used.
- * @return Error code
- */
-int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
-{
-	assert(instance);
-	int ret;
-	fibril_mutex_lock(&instance->guard);
-	if (target.endpoint > 15 || target.endpoint < 0
-	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
-	    || !instance->devices[target.address].occupied) {
-		usb_log_error("Invalid data when asking for toggle value.\n");
-		ret = EINVAL;
-	} else {
-		ret = (instance->devices[target.address].toggle_status
-		        >> target.endpoint) & 1;
-	}
-	fibril_mutex_unlock(&instance->guard);
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Set current value of endpoint toggle.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] target Device and endpoint used.
- * @param[in] toggle Toggle value.
- * @return Error code.
- */
-int device_keeper_set_toggle(
-    device_keeper_t *instance, usb_target_t target, bool toggle)
-{
-	assert(instance);
-	int ret;
-	fibril_mutex_lock(&instance->guard);
-	if (target.endpoint > 15 || target.endpoint < 0
-	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
-	    || !instance->devices[target.address].occupied) {
-		usb_log_error("Invalid data when setting toggle value.\n");
-		ret = EINVAL;
-	} else {
-		if (toggle) {
-			instance->devices[target.address].toggle_status |= (1 << target.endpoint);
-		} else {
-			instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
-		}
-		ret = EOK;
-	}
-	fibril_mutex_unlock(&instance->guard);
-	return ret;
-}
-/*----------------------------------------------------------------------------*/
-/** Get a free USB address
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] speed Speed of the device requiring address.
- * @return Free address, or error code.
- */
-usb_address_t device_keeper_request(
-    device_keeper_t *instance, usb_speed_t speed)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-
-	usb_address_t new_address = instance->last_address + 1;
-	while (instance->devices[new_address].occupied) {
-		if (new_address == instance->last_address) {
-			fibril_mutex_unlock(&instance->guard);
-			return ENOSPC;
-		}
-		if (new_address == USB11_ADDRESS_MAX)
-			new_address = 1;
-		++new_address;
-	}
-
-	assert(new_address != USB_ADDRESS_DEFAULT);
-	assert(instance->devices[new_address].occupied == false);
-	instance->devices[new_address].occupied = true;
-	instance->devices[new_address].speed = speed;
-	instance->devices[new_address].toggle_status = 0;
-	instance->last_address = new_address;
-	fibril_mutex_unlock(&instance->guard);
-	return new_address;
-}
-/*----------------------------------------------------------------------------*/
-/** Bind USB address to devman handle.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] address Device address
- * @param[in] handle Devman handle of the device.
- */
-void device_keeper_bind(
-    device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	assert(address > 0);
-	assert(address <= USB11_ADDRESS_MAX);
-	assert(instance->devices[address].occupied);
-	instance->devices[address].handle = handle;
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Release used USB address.
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] address Device address
- */
-void device_keeper_release(device_keeper_t *instance, usb_address_t address)
-{
-	assert(instance);
-	assert(address > 0);
-	assert(address <= USB11_ADDRESS_MAX);
-
-	fibril_mutex_lock(&instance->guard);
-	assert(instance->devices[address].occupied);
-	instance->devices[address].occupied = false;
-	fibril_mutex_unlock(&instance->guard);
-}
-/*----------------------------------------------------------------------------*/
-/** Find USB address associated with the device
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] handle Devman handle of the device seeking its address.
- * @return USB Address, or error code.
- */
-usb_address_t device_keeper_find(
-    device_keeper_t *instance, devman_handle_t handle)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	usb_address_t address = 1;
-	while (address <= USB11_ADDRESS_MAX) {
-		if (instance->devices[address].handle == handle) {
-			fibril_mutex_unlock(&instance->guard);
-			return address;
-		}
-		++address;
-	}
-	fibril_mutex_unlock(&instance->guard);
-	return ENOENT;
-}
-/*----------------------------------------------------------------------------*/
-/** Get speed associated with the address
- *
- * @param[in] instance Device keeper structure to use.
- * @param[in] address Address of the device.
- * @return USB speed.
- */
-usb_speed_t device_keeper_speed(
-    device_keeper_t *instance, usb_address_t address)
-{
-	assert(instance);
-	assert(address >= 0);
-	assert(address <= USB11_ADDRESS_MAX);
-	return instance->devices[address].speed;
-}
-/**
- * @}
- */
Index: pace/drv/uhci-hcd/utils/device_keeper.h
===================================================================
--- uspace/drv/uhci-hcd/utils/device_keeper.h	(revision e7bc999ad582830200c9cdebcd975dc5ed9cc969)
+++ 	(revision )
@@ -1,88 +1,0 @@
-/*
- * Copyright (c) 2011 Jan Vesely
- * 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 drvusbuhcihc
- * @{
- */
-/** @file
- * @brief UHCI driver
- */
-#ifndef UTILS_DEVICE_KEEPER_H
-#define UTILS_DEVICE_KEEPER_H
-#include <devman.h>
-#include <fibril_synch.h>
-#include <usb/usb.h>
-
-#define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1)
-
-struct usb_device_info {
-	usb_speed_t speed;
-	bool occupied;
-	uint16_t toggle_status;
-	devman_handle_t handle;
-};
-
-typedef struct device_keeper {
-	struct usb_device_info devices[USB_ADDRESS_COUNT];
-	fibril_mutex_t guard;
-	fibril_condvar_t default_address_occupied;
-	usb_address_t last_address;
-} device_keeper_t;
-
-void device_keeper_init(device_keeper_t *instance);
-
-void device_keeper_reserve_default(
-    device_keeper_t *instance, usb_speed_t speed);
-
-void device_keeper_release_default(device_keeper_t *instance);
-
-void device_keeper_reset_if_need(
-    device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);
-
-int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);
-
-int device_keeper_set_toggle(
-    device_keeper_t *instance, usb_target_t target, bool toggle);
-
-usb_address_t device_keeper_request(
-    device_keeper_t *instance, usb_speed_t speed);
-
-void device_keeper_bind(
-    device_keeper_t *instance, usb_address_t address, devman_handle_t handle);
-
-void device_keeper_release(device_keeper_t *instance, usb_address_t address);
-
-usb_address_t device_keeper_find(
-    device_keeper_t *instance, devman_handle_t handle);
-
-usb_speed_t device_keeper_speed(
-    device_keeper_t *instance, usb_address_t address);
-#endif
-/**
- * @}
- */
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision e7bc999ad582830200c9cdebcd975dc5ed9cc969)
+++ uspace/lib/usb/Makefile	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
@@ -49,5 +49,6 @@
 	src/request.c \
 	src/usb.c \
-	src/usbdevice.c
+	src/usbdevice.c \
+	src/host/device_keeper.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usb/include/usb/host/device_keeper.h	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
+++ uspace/lib/usb/include/usb/host/device_keeper.h	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef UTILS_DEVICE_KEEPER_H
+#define UTILS_DEVICE_KEEPER_H
+#include <devman.h>
+#include <fibril_synch.h>
+#include <usb/usb.h>
+
+#define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1)
+
+struct usb_device_info {
+	usb_speed_t speed;
+	bool occupied;
+	uint16_t toggle_status;
+	devman_handle_t handle;
+};
+
+typedef struct device_keeper {
+	struct usb_device_info devices[USB_ADDRESS_COUNT];
+	fibril_mutex_t guard;
+	fibril_condvar_t default_address_occupied;
+	usb_address_t last_address;
+} device_keeper_t;
+
+void device_keeper_init(device_keeper_t *instance);
+
+void device_keeper_reserve_default(
+    device_keeper_t *instance, usb_speed_t speed);
+
+void device_keeper_release_default(device_keeper_t *instance);
+
+void device_keeper_reset_if_need(
+    device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);
+
+int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);
+
+int device_keeper_set_toggle(
+    device_keeper_t *instance, usb_target_t target, bool toggle);
+
+usb_address_t device_keeper_request(
+    device_keeper_t *instance, usb_speed_t speed);
+
+void device_keeper_bind(
+    device_keeper_t *instance, usb_address_t address, devman_handle_t handle);
+
+void device_keeper_release(device_keeper_t *instance, usb_address_t address);
+
+usb_address_t device_keeper_find(
+    device_keeper_t *instance, devman_handle_t handle);
+
+usb_speed_t device_keeper_speed(
+    device_keeper_t *instance, usb_address_t address);
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/host/device_keeper.c
===================================================================
--- uspace/lib/usb/src/host/device_keeper.c	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
+++ uspace/lib/usb/src/host/device_keeper.c	(revision 1fb1339c2806d3d992b780c1f6c3a411fc3fdfe6)
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * 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
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+#include <usb/debug.h>
+#include <usb/host/device_keeper.h>
+
+/*----------------------------------------------------------------------------*/
+/** Initialize device keeper structure.
+ *
+ * @param[in] instance Memory place to initialize.
+ *
+ * Set all values to false/0.
+ */
+void device_keeper_init(device_keeper_t *instance)
+{
+	assert(instance);
+	fibril_mutex_initialize(&instance->guard);
+	fibril_condvar_initialize(&instance->default_address_occupied);
+	instance->last_address = 0;
+	unsigned i = 0;
+	for (; i < USB_ADDRESS_COUNT; ++i) {
+		instance->devices[i].occupied = false;
+		instance->devices[i].handle = 0;
+		instance->devices[i].toggle_status = 0;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Attempt to obtain address 0, blocks.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] speed Speed of the device requesting default address.
+ */
+void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
+		fibril_condvar_wait(&instance->default_address_occupied,
+		    &instance->guard);
+	}
+	instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
+	instance->devices[USB_ADDRESS_DEFAULT].speed = speed;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Attempt to obtain address 0, blocks.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] speed Speed of the device requesting default address.
+ */
+void device_keeper_release_default(device_keeper_t *instance)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_signal(&instance->default_address_occupied);
+}
+/*----------------------------------------------------------------------------*/
+/** Check setup packet data for signs of toggle reset.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device to receive setup packet.
+ * @param[in] data Setup packet data.
+ *
+ * Really ugly one.
+ */
+void device_keeper_reset_if_need(
+    device_keeper_t *instance, usb_target_t target, const unsigned char *data)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		fibril_mutex_unlock(&instance->guard);
+		usb_log_error("Invalid data when checking for toggle reset.\n");
+		return;
+	}
+
+	switch (data[1])
+	{
+	case 0x01: /*clear feature*/
+		/* recipient is endpoint, value is zero (ENDPOINT_STALL) */
+		if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
+			/* endpoint number is < 16, thus first byte is enough */
+			instance->devices[target.address].toggle_status &=
+			    ~(1 << data[4]);
+		}
+	break;
+
+	case 0x9: /* set configuration */
+	case 0x11: /* set interface */
+		/* target must be device */
+		if ((data[0] & 0xf) == 0) {
+			instance->devices[target.address].toggle_status = 0;
+		}
+	break;
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Get current value of endpoint toggle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device and endpoint used.
+ * @return Error code
+ */
+int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
+{
+	assert(instance);
+	int ret;
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		usb_log_error("Invalid data when asking for toggle value.\n");
+		ret = EINVAL;
+	} else {
+		ret = (instance->devices[target.address].toggle_status
+		        >> target.endpoint) & 1;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Set current value of endpoint toggle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device and endpoint used.
+ * @param[in] toggle Toggle value.
+ * @return Error code.
+ */
+int device_keeper_set_toggle(
+    device_keeper_t *instance, usb_target_t target, bool toggle)
+{
+	assert(instance);
+	int ret;
+	fibril_mutex_lock(&instance->guard);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB_ADDRESS_COUNT || target.address < 0
+	    || !instance->devices[target.address].occupied) {
+		usb_log_error("Invalid data when setting toggle value.\n");
+		ret = EINVAL;
+	} else {
+		if (toggle) {
+			instance->devices[target.address].toggle_status |= (1 << target.endpoint);
+		} else {
+			instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);
+		}
+		ret = EOK;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Get a free USB address
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] speed Speed of the device requiring address.
+ * @return Free address, or error code.
+ */
+usb_address_t device_keeper_request(
+    device_keeper_t *instance, usb_speed_t speed)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+
+	usb_address_t new_address = instance->last_address + 1;
+	while (instance->devices[new_address].occupied) {
+		if (new_address == instance->last_address) {
+			fibril_mutex_unlock(&instance->guard);
+			return ENOSPC;
+		}
+		if (new_address == USB11_ADDRESS_MAX)
+			new_address = 1;
+		++new_address;
+	}
+
+	assert(new_address != USB_ADDRESS_DEFAULT);
+	assert(instance->devices[new_address].occupied == false);
+	instance->devices[new_address].occupied = true;
+	instance->devices[new_address].speed = speed;
+	instance->devices[new_address].toggle_status = 0;
+	instance->last_address = new_address;
+	fibril_mutex_unlock(&instance->guard);
+	return new_address;
+}
+/*----------------------------------------------------------------------------*/
+/** Bind USB address to devman handle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Device address
+ * @param[in] handle Devman handle of the device.
+ */
+void device_keeper_bind(
+    device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	assert(address > 0);
+	assert(address <= USB11_ADDRESS_MAX);
+	assert(instance->devices[address].occupied);
+	instance->devices[address].handle = handle;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Release used USB address.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Device address
+ */
+void device_keeper_release(device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address > 0);
+	assert(address <= USB11_ADDRESS_MAX);
+
+	fibril_mutex_lock(&instance->guard);
+	assert(instance->devices[address].occupied);
+	instance->devices[address].occupied = false;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Find USB address associated with the device
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] handle Devman handle of the device seeking its address.
+ * @return USB Address, or error code.
+ */
+usb_address_t device_keeper_find(
+    device_keeper_t *instance, devman_handle_t handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	usb_address_t address = 1;
+	while (address <= USB11_ADDRESS_MAX) {
+		if (instance->devices[address].handle == handle) {
+			fibril_mutex_unlock(&instance->guard);
+			return address;
+		}
+		++address;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ENOENT;
+}
+/*----------------------------------------------------------------------------*/
+/** Get speed associated with the address
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Address of the device.
+ * @return USB speed.
+ */
+usb_speed_t device_keeper_speed(
+    device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address >= 0);
+	assert(address <= USB11_ADDRESS_MAX);
+	return instance->devices[address].speed;
+}
+/**
+ * @}
+ */
