Index: uspace/lib/usbhost/Makefile
===================================================================
--- uspace/lib/usbhost/Makefile	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/Makefile	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+LIBRARY = libusbhost
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include \
+	-Iinclude
+
+SOURCES = \
+	src/addrkeep.c \
+	src/batch.c \
+	src/device_keeper.c \
+	src/endpoint.c \
+	src/usb_endpoint_manager.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usbhost/include/usb/addrkeep.h
===================================================================
--- uspace/lib/usbhost/include/usb/addrkeep.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/include/usb/addrkeep.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,86 @@
+/*
+ * 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
+ * @{
+ */
+/** @file
+ * USB address keeping for host controller drivers.
+ */
+#ifndef LIBUSB_ADDRKEEP_H_
+#define LIBUSB_ADDRKEEP_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/usbhost/include/usb/host/batch.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/batch.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/include/usb/host/batch.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,101 @@
+/*
+ * 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
+ * USB transfer transaction structures.
+ */
+#ifndef LIBUSB_HOST_BATCH_H
+#define LIBUSB_HOST_BATCH_H
+
+#include <adt/list.h>
+
+#include <usbhc_iface.h>
+#include <usb/usb.h>
+#include <usb/host/endpoint.h>
+
+typedef struct usb_transfer_batch usb_transfer_batch_t;
+struct usb_transfer_batch {
+	endpoint_t *ep;
+	link_t link;
+	usbhc_iface_transfer_in_callback_t callback_in;
+	usbhc_iface_transfer_out_callback_t callback_out;
+	void *arg;
+	char *buffer;
+	char *data_buffer;
+	size_t buffer_size;
+	char *setup_buffer;
+	size_t setup_size;
+	size_t transfered_size;
+	void (*next_step)(usb_transfer_batch_t *);
+	int error;
+	ddf_fun_t *fun;
+	void *private_data;
+	void (*private_data_dtor)(void *p_data);
+};
+
+void usb_transfer_batch_init(
+    usb_transfer_batch_t *instance,
+    endpoint_t *ep,
+    char *buffer,
+    char *data_buffer,
+    size_t buffer_size,
+    char *setup_buffer,
+    size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out,
+    void *arg,
+    ddf_fun_t *fun,
+    void *private_data,
+    void (*private_data_dtor)(void *p_data)
+);
+
+void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance);
+void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance);
+void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
+void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
+
+static inline void usb_transfer_batch_finish_error(
+    usb_transfer_batch_t *instance, int error)
+{
+	assert(instance);
+	instance->error = error;
+	usb_transfer_batch_finish(instance);
+}
+
+static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
+{
+	assert(l);
+	return list_get_instance(l, usb_transfer_batch_t, link);
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/device_keeper.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/include/usb/host/device_keeper.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,90 @@
+/*
+ * 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
+ * Device keeper structure and functions.
+ *
+ * Typical USB host controller needs to keep track of various settings for
+ * each device that is connected to it.
+ * State of toggle bit, device speed etc. etc.
+ * This structure shall simplify the management.
+ */
+#ifndef LIBUSB_HOST_DEVICE_KEEPER_H
+#define LIBUSB_HOST_DEVICE_KEEPER_H
+
+#include <adt/list.h>
+#include <devman.h>
+#include <fibril_synch.h>
+#include <usb/usb.h>
+#include <usb/host/endpoint.h>
+
+/** Number of USB address for array dimensions. */
+#define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1)
+
+/** Information about attached USB device. */
+struct usb_device_info {
+	usb_speed_t speed;
+	bool occupied;
+	devman_handle_t handle;
+};
+
+/** Host controller device keeper.
+ * You shall not access members directly but only using functions below.
+ */
+typedef struct {
+	struct usb_device_info devices[USB_ADDRESS_COUNT];
+	fibril_mutex_t guard;
+	usb_address_t last_address;
+} usb_device_keeper_t;
+
+void usb_device_keeper_init(usb_device_keeper_t *instance);
+
+usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
+    usb_speed_t speed);
+
+void usb_device_keeper_bind(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t handle);
+
+void usb_device_keeper_release(usb_device_keeper_t *instance,
+    usb_address_t address);
+
+usb_address_t usb_device_keeper_find(usb_device_keeper_t *instance,
+    devman_handle_t handle);
+
+bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t *handle);
+
+usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
+    usb_address_t address);
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,86 @@
+/*
+ * 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
+ *
+ */
+#ifndef LIBUSB_HOST_ENDPOINT_H
+#define LIBUSB_HOST_ENDPOINT_H
+
+#include <assert.h>
+#include <bool.h>
+#include <adt/list.h>
+#include <fibril_synch.h>
+
+#include <usb/usb.h>
+
+typedef struct endpoint {
+	usb_address_t address;
+	usb_endpoint_t endpoint;
+	usb_direction_t direction;
+	usb_transfer_type_t transfer_type;
+	usb_speed_t speed;
+	size_t max_packet_size;
+	unsigned toggle:1;
+	fibril_mutex_t guard;
+	fibril_condvar_t avail;
+	volatile bool active;
+	struct {
+		void *data;
+		int (*toggle_get)(void *);
+		void (*toggle_set)(void *, int);
+	} hc_data;
+} endpoint_t;
+
+int endpoint_init(endpoint_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction,
+    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size);
+
+void endpoint_destroy(endpoint_t *instance);
+
+void endpoint_set_hc_data(endpoint_t *instance,
+    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
+
+void endpoint_clear_hc_data(endpoint_t *instance);
+
+void endpoint_use(endpoint_t *instance);
+
+void endpoint_release(endpoint_t *instance);
+
+int endpoint_toggle_get(endpoint_t *instance);
+
+void endpoint_toggle_set(endpoint_t *instance, int toggle);
+
+void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,105 @@
+/*
+ * 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
+ * Device keeper structure and functions.
+ *
+ * Typical USB host controller needs to keep track of various settings for
+ * each device that is connected to it.
+ * State of toggle bit, device speed etc. etc.
+ * This structure shall simplify the management.
+ */
+#ifndef LIBUSB_HOST_USB_ENDPOINT_MANAGER_H
+#define LIBUSB_HOST_YSB_ENDPOINT_MANAGER_H
+
+#include <adt/hash_table.h>
+#include <fibril_synch.h>
+#include <usb/usb.h>
+#include <usb/host/endpoint.h>
+
+#define BANDWIDTH_TOTAL_USB11 12000000
+#define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9)
+
+typedef struct usb_endpoint_manager {
+	hash_table_t ep_table;
+	fibril_mutex_t guard;
+	fibril_condvar_t change;
+	size_t free_bw;
+} usb_endpoint_manager_t;
+
+size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type,
+    size_t size, size_t max_packet_size);
+
+int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
+    size_t available_bandwidth);
+
+void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance);
+
+int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
+    endpoint_t *ep, size_t data_size);
+
+int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction);
+
+endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,
+    size_t *bw);
+
+void usb_endpoint_manager_reset_if_need(
+    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
+
+static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
+    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
+    size_t data_size)
+{
+	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	if (ep == NULL)
+		return ENOMEM;
+
+	int ret = endpoint_init(ep, address, endpoint, direction, type, speed,
+	    max_packet_size);
+	if (ret != EOK) {
+		free(ep);
+		return ret;
+	}
+
+	ret = usb_endpoint_manager_register_ep(instance, ep, data_size);
+	if (ret != EOK) {
+		endpoint_destroy(ep);
+		return ret;
+	}
+	return EOK;
+}
+#endif
+/**
+ * @}
+ */
+
Index: uspace/lib/usbhost/src/addrkeep.c
===================================================================
--- uspace/lib/usbhost/src/addrkeep.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/src/addrkeep.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,347 @@
+/*
+ * 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
+ * @{
+ */
+/** @file
+ * @brief Address keeping.
+ */
+#include <usb/addrkeep.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);
+	}
+	addresses->default_available = false;
+	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 {
+		usb_address_keeping_used_t *first
+		    = used_address_get_instance(addresses->used_addresses.next);
+		previous_address = first->address;
+		
+		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;
+			}
+			previous_address = info->address;
+		}
+
+		if (free_address == 0) {
+			usb_address_keeping_used_t *last
+			    = used_address_get_instance(addresses->used_addresses.next);
+			free_address = last->address + 1;
+		}
+	}
+
+	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/usbhost/src/batch.c
===================================================================
--- uspace/lib/usbhost/src/batch.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/src/batch.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,176 @@
+/*
+ * 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
+ * USB transfer transaction structures (implementation).
+ */
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/usb.h>
+#include <usb/debug.h>
+#include <usb/host/batch.h>
+
+void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
+void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
+
+void usb_transfer_batch_init(
+    usb_transfer_batch_t *instance,
+    endpoint_t *ep,
+    char *buffer,
+    char *data_buffer,
+    size_t buffer_size,
+    char *setup_buffer,
+    size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out,
+    void *arg,
+    ddf_fun_t *fun,
+    void *private_data,
+    void (*private_data_dtor)(void *p_data)
+    )
+{
+	assert(instance);
+	link_initialize(&instance->link);
+	instance->ep = ep;
+	instance->callback_in = func_in;
+	instance->callback_out = func_out;
+	instance->arg = arg;
+	instance->buffer = buffer;
+	instance->data_buffer = data_buffer;
+	instance->buffer_size = buffer_size;
+	instance->setup_buffer = setup_buffer;
+	instance->setup_size = setup_size;
+	instance->fun = fun;
+	instance->private_data = private_data;
+	instance->private_data_dtor = private_data_dtor;
+	instance->transfered_size = 0;
+	instance->next_step = NULL;
+	instance->error = EOK;
+	endpoint_use(instance->ep);
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function, calls callback and correctly destroys batch structure.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_transfer_batch_call_in(instance);
+	usb_transfer_batch_dispose(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function calls callback and correctly destroys batch structure.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_transfer_batch_call_out(instance);
+	usb_transfer_batch_dispose(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Mark batch as finished and continue with next step.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ */
+void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	assert(instance->ep);
+	endpoint_release(instance->ep);
+	instance->next_step(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare data, get error status and call callback in.
+ *
+ * @param[in] instance Batch structure to use.
+ * Copies data from transport buffer, and calls callback with appropriate
+ * parameters.
+ */
+void usb_transfer_batch_call_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_in);
+	assert(instance->ep);
+
+	/* We are data in, we need data */
+	memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
+
+	usb_log_debug("Batch(%p) done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
+	    instance, instance->ep->address, instance->ep->endpoint,
+	    usb_str_speed(instance->ep->speed),
+	    usb_str_transfer_type_short(instance->ep->transfer_type),
+	    instance->transfered_size, str_error(instance->error),
+	    instance->error);
+
+	instance->callback_in(instance->fun, instance->error,
+	    instance->transfered_size, instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+/** Get error status and call callback out.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_call_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_out);
+
+	usb_log_debug("Batch(%p) done (T%d.%d, %s %s out): %s (%d).\n",
+	    instance, instance->ep->address, instance->ep->endpoint,
+	    usb_str_speed(instance->ep->speed),
+	    usb_str_transfer_type_short(instance->ep->transfer_type),
+	    str_error(instance->error), instance->error);
+
+	instance->callback_out(instance->fun,
+	    instance->error, instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+/** Correctly dispose all used data structures.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_log_debug("Batch(%p) disposing.\n", instance);
+	if (instance->private_data) {
+		assert(instance->private_data_dtor);
+		instance->private_data_dtor(instance->private_data);
+	}
+	free(instance);
+}
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/src/device_keeper.c
===================================================================
--- uspace/lib/usbhost/src/device_keeper.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/src/device_keeper.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,207 @@
+/*
+ * 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
+ * Device keeper structure and functions (implementation).
+ */
+#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 usb_device_keeper_init(usb_device_keeper_t *instance)
+{
+	assert(instance);
+	unsigned i = 0;
+	for (; i < USB_ADDRESS_COUNT; ++i) {
+		instance->devices[i].occupied = false;
+		instance->devices[i].handle = 0;
+		instance->devices[i].speed = USB_SPEED_MAX;
+	}
+	// TODO: is this hack enough?
+	// (it is needed to allow smooth registration at default address)
+	instance->devices[0].occupied = true;
+	instance->last_address = 0;
+	fibril_mutex_initialize(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** 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_get_free_address(
+    usb_device_keeper_t *instance, usb_speed_t speed)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+
+	usb_address_t new_address = instance->last_address;
+	do {
+		++new_address;
+		if (new_address > USB11_ADDRESS_MAX)
+			new_address = 1;
+		if (new_address == instance->last_address) {
+			fibril_mutex_unlock(&instance->guard);
+			return ENOSPC;
+		}
+	} while (instance->devices[new_address].occupied);
+
+	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->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 usb_device_keeper_bind(usb_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 usb_device_keeper_release(
+    usb_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 usb_device_keeper_find(
+    usb_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) {
+			assert(instance->devices[address].occupied);
+			fibril_mutex_unlock(&instance->guard);
+			return address;
+		}
+		++address;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ENOENT;
+}
+
+/** Find devman handled assigned to USB address.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Address the caller wants to find.
+ * @param[out] handle Where to store found handle.
+ * @return Whether such address is currently occupied.
+ */
+bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t *handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
+		fibril_mutex_unlock(&instance->guard);
+		return false;
+	}
+	if (!instance->devices[address].occupied) {
+		fibril_mutex_unlock(&instance->guard);
+		return false;
+	}
+
+	if (handle != NULL) {
+		*handle = instance->devices[address].handle;
+	}
+
+	fibril_mutex_unlock(&instance->guard);
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+/** 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 usb_device_keeper_get_speed(
+    usb_device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address >= 0);
+	assert(address <= USB11_ADDRESS_MAX);
+
+	return instance->devices[address].speed;
+}
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/src/endpoint.c
===================================================================
--- uspace/lib/usbhost/src/endpoint.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/src/endpoint.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,129 @@
+/*
+ * 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 host controller driver structure
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <usb/host/endpoint.h>
+
+int endpoint_init(endpoint_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction,
+    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size)
+{
+	assert(instance);
+	instance->address = address;
+	instance->endpoint = endpoint;
+	instance->direction = direction;
+	instance->transfer_type = type;
+	instance->speed = speed;
+	instance->max_packet_size = max_packet_size;
+	instance->toggle = 0;
+	instance->active = false;
+	fibril_mutex_initialize(&instance->guard);
+	fibril_condvar_initialize(&instance->avail);
+	endpoint_clear_hc_data(instance);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_destroy(endpoint_t *instance)
+{
+	assert(instance);
+	assert(!instance->active);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_set_hc_data(endpoint_t *instance,
+    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
+{
+	assert(instance);
+	instance->hc_data.data = data;
+	instance->hc_data.toggle_get = toggle_get;
+	instance->hc_data.toggle_set = toggle_set;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_clear_hc_data(endpoint_t *instance)
+{
+	assert(instance);
+	instance->hc_data.data = NULL;
+	instance->hc_data.toggle_get = NULL;
+	instance->hc_data.toggle_set = NULL;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_use(endpoint_t *instance)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	while (instance->active)
+		fibril_condvar_wait(&instance->avail, &instance->guard);
+	instance->active = true;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_release(endpoint_t *instance)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	instance->active = false;
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_signal(&instance->avail);
+}
+/*----------------------------------------------------------------------------*/
+int endpoint_toggle_get(endpoint_t *instance)
+{
+	assert(instance);
+	if (instance->hc_data.toggle_get)
+		instance->toggle =
+		    instance->hc_data.toggle_get(instance->hc_data.data);
+	return (int)instance->toggle;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_toggle_set(endpoint_t *instance, int toggle)
+{
+	assert(instance);
+	assert(toggle == 0 || toggle == 1);
+	if (instance->hc_data.toggle_set)
+		instance->hc_data.toggle_set(instance->hc_data.data, toggle);
+	instance->toggle = toggle;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
+{
+	assert(instance);
+	if (instance->address == target.address &&
+	    (instance->endpoint == target.endpoint || target.endpoint == 0))
+		endpoint_toggle_set(instance, 0);
+}
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/src/usb_endpoint_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
+++ uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision 3e4f2e0be68fb7237dac816aa68461e328a38b03)
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights eps.
+ *
+ * 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 <bool.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+#include <usb/host/usb_endpoint_manager.h>
+
+#define BUCKET_COUNT 7
+
+#define MAX_KEYS (3)
+typedef struct {
+	link_t link;
+	size_t bw;
+	endpoint_t *ep;
+} node_t;
+/*----------------------------------------------------------------------------*/
+static hash_index_t node_hash(unsigned long key[])
+{
+	hash_index_t hash = 0;
+	unsigned i = 0;
+	for (;i < MAX_KEYS; ++i) {
+		hash ^= key[i];
+	}
+	hash %= BUCKET_COUNT;
+	return hash;
+}
+/*----------------------------------------------------------------------------*/
+static int node_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	assert(item);
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	assert(node);
+	assert(node->ep);
+	bool match = true;
+	switch (keys) {
+	case 3:
+		match = match && (key[2] == node->ep->direction);
+	case 2:
+		match = match && (key[1] == (unsigned long)node->ep->endpoint);
+	case 1:
+		match = match && (key[0] == (unsigned long)node->ep->address);
+		break;
+	default:
+		match = false;
+	}
+	return match;
+}
+/*----------------------------------------------------------------------------*/
+static void node_remove(link_t *item)
+{
+	assert(item);
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	endpoint_destroy(node->ep);
+	free(node);
+}
+/*----------------------------------------------------------------------------*/
+static void node_toggle_reset_filtered(link_t *item, void *arg)
+{
+	assert(item);
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	usb_target_t *target = arg;
+	endpoint_toggle_reset_filtered(node->ep, *target);
+}
+/*----------------------------------------------------------------------------*/
+static hash_table_operations_t op = {
+	.hash = node_hash,
+	.compare = node_compare,
+	.remove_callback = node_remove,
+};
+/*----------------------------------------------------------------------------*/
+size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type,
+    size_t size, size_t max_packet_size)
+{
+	/* We care about bandwidth only for interrupt and isochronous. */
+	if ((type != USB_TRANSFER_INTERRUPT)
+	    && (type != USB_TRANSFER_ISOCHRONOUS)) {
+		return 0;
+	}
+
+	const unsigned packet_count =
+	    (size + max_packet_size - 1) / max_packet_size;
+	/* TODO: It may be that ISO and INT transfers use only one data packet
+	 * per transaction, but I did not find text in UB spec that confirms
+	 * this */
+	/* NOTE: All data packets will be considered to be max_packet_size */
+	switch (speed)
+	{
+	case USB_SPEED_LOW:
+		assert(type == USB_TRANSFER_INTERRUPT);
+		/* Protocol overhead 13B
+		 * (3 SYNC bytes, 3 PID bytes, 2 Endpoint + CRC bytes, 2
+		 * CRC bytes, and a 3-byte interpacket delay)
+		 * see USB spec page 45-46. */
+		/* Speed penalty 8: low speed is 8-times slower*/
+		return packet_count * (13 + max_packet_size) * 8;
+	case USB_SPEED_FULL:
+		/* Interrupt transfer overhead see above
+		 * or page 45 of USB spec */
+		if (type == USB_TRANSFER_INTERRUPT)
+			return packet_count * (13 + max_packet_size);
+
+		assert(type == USB_TRANSFER_ISOCHRONOUS);
+		/* Protocol overhead 9B
+		 * (2 SYNC bytes, 2 PID bytes, 2 Endpoint + CRC bytes, 2 CRC
+		 * bytes, and a 1-byte interpacket delay)
+		 * see USB spec page 42 */
+		return packet_count * (9 + max_packet_size);
+	default:
+		return 0;
+	}
+}
+/*----------------------------------------------------------------------------*/
+int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
+    size_t available_bandwidth)
+{
+	assert(instance);
+	fibril_mutex_initialize(&instance->guard);
+	fibril_condvar_initialize(&instance->change);
+	instance->free_bw = available_bandwidth;
+	bool ht =
+	    hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op);
+	return ht ? EOK : ENOMEM;
+}
+/*----------------------------------------------------------------------------*/
+void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance)
+{
+	hash_table_destroy(&instance->ep_table);
+}
+/*----------------------------------------------------------------------------*/
+int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
+    endpoint_t *ep, size_t data_size)
+{
+	assert(ep);
+	size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
+	    data_size, ep->max_packet_size);
+	assert(instance);
+
+	unsigned long key[MAX_KEYS] =
+	    {ep->address, ep->endpoint, ep->direction};
+	fibril_mutex_lock(&instance->guard);
+
+	link_t *item =
+	    hash_table_find(&instance->ep_table, key);
+	if (item != NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return EEXISTS;
+	}
+
+	if (bw > instance->free_bw) {
+		fibril_mutex_unlock(&instance->guard);
+		return ENOSPC;
+	}
+
+	node_t *node = malloc(sizeof(node_t));
+	if (node == NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return ENOMEM;
+	}
+
+	node->bw = bw;
+	node->ep = ep;
+	link_initialize(&node->link);
+
+	hash_table_insert(&instance->ep_table, key, &node->link);
+	instance->free_bw -= bw;
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_broadcast(&instance->change);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(instance);
+	unsigned long key[MAX_KEYS] = {address, endpoint, direction};
+
+	fibril_mutex_lock(&instance->guard);
+	link_t *item = hash_table_find(&instance->ep_table, key);
+	if (item == NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return EINVAL;
+	}
+
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	if (node->ep->active)
+		return EBUSY;
+
+	instance->free_bw += node->bw;
+	hash_table_remove(&instance->ep_table, key, MAX_KEYS);
+
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_broadcast(&instance->change);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
+    size_t *bw)
+{
+	assert(instance);
+	unsigned long key[MAX_KEYS] = {address, endpoint, direction};
+
+	fibril_mutex_lock(&instance->guard);
+	link_t *item = hash_table_find(&instance->ep_table, key);
+	if (item == NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return NULL;
+	}
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	if (bw)
+		*bw = node->bw;
+
+	fibril_mutex_unlock(&instance->guard);
+	return node->ep;
+}
+/*----------------------------------------------------------------------------*/
+/** 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 usb_endpoint_manager_reset_if_need(
+    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)
+{
+	assert(instance);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
+		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 */
+			usb_target_t reset_target =
+			    { .address = target.address, data[4] };
+			fibril_mutex_lock(&instance->guard);
+			hash_table_apply(&instance->ep_table,
+			    node_toggle_reset_filtered, &reset_target);
+			fibril_mutex_unlock(&instance->guard);
+		}
+	break;
+
+	case 0x9: /* set configuration */
+	case 0x11: /* set interface */
+		/* target must be device */
+		if ((data[0] & 0xf) == 0) {
+			usb_target_t reset_target =
+			    { .address = target.address, 0 };
+			fibril_mutex_lock(&instance->guard);
+			hash_table_apply(&instance->ep_table,
+			    node_toggle_reset_filtered, &reset_target);
+			fibril_mutex_unlock(&instance->guard);
+		}
+	break;
+	}
+}
