Index: uspace/drv/uhci-hcd/hc.c
===================================================================
--- uspace/drv/uhci-hcd/hc.c	(revision 8123695a05edc85df5433b25264e0e8c0cbf18a2)
+++ uspace/drv/uhci-hcd/hc.c	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -239,4 +239,8 @@
 	usb_log_debug("Initialized device manager.\n");
 
+	ret = bandwidth_init(&instance->bandwidth, BANDWIDTH_AVAILABLE_USB11,
+	    bandwidth_count_usb11);
+	assert(ret == true);
+
 	return EOK;
 #undef CHECK_RET_DEST_CMDS_RETURN
@@ -325,11 +329,20 @@
 	if (!usb_is_allowed(
 	    low_speed, batch->transfer_type, batch->max_packet_size)) {
-		usb_log_warning(
-		    "Invalid USB transfer specified %s SPEED %d %zu.\n",
-		    low_speed ? "LOW" : "FULL" , batch->transfer_type,
+		usb_log_error("Invalid USB transfer specified %s %d %zu.\n",
+		    usb_str_speed(batch->speed), batch->transfer_type,
 		    batch->max_packet_size);
 		return ENOTSUP;
 	}
-	/* TODO: check available bandwidth here */
+	/* Check available bandwidth */
+	if (batch->transfer_type == USB_TRANSFER_INTERRUPT ||
+	    batch->transfer_type == USB_TRANSFER_ISOCHRONOUS) {
+		int ret =
+		    bandwidth_use(&instance->bandwidth, batch->target.address,
+		    batch->target.endpoint, batch->direction);
+		if (ret != EOK) {
+			usb_log_warning("Failed(%d) to use reserved bw: %s.\n",
+			    ret, str_error(ret));
+		}
+	}
 
 	transfer_list_t *list =
@@ -338,5 +351,5 @@
 	if (batch->transfer_type == USB_TRANSFER_CONTROL) {
 		usb_device_keeper_use_control(
-		    &instance->manager, batch->target.address);
+		    &instance->manager, batch->target);
 	}
 	transfer_list_add_batch(list, batch);
@@ -358,4 +371,5 @@
 {
 	assert(instance);
+//	status |= 1; //Uncomment to work around qemu hang
 	/* TODO: Resume interrupts are not supported */
 	/* Lower 2 bits are transaction error and transaction complete */
@@ -376,7 +390,23 @@
 			usb_transfer_batch_t *batch =
 			    list_get_instance(item, usb_transfer_batch_t, link);
-			if (batch->transfer_type == USB_TRANSFER_CONTROL) {
+			switch (batch->transfer_type)
+			{
+			case USB_TRANSFER_CONTROL:
 				usb_device_keeper_release_control(
-				    &instance->manager, batch->target.address);
+				    &instance->manager, batch->target);
+				break;
+			case USB_TRANSFER_INTERRUPT:
+			case USB_TRANSFER_ISOCHRONOUS: {
+				int ret = bandwidth_free(&instance->bandwidth,
+				    batch->target.address,
+				    batch->target.endpoint,
+				    batch->direction);
+				if (ret != EOK)
+					usb_log_warning("Failed(%d) to free "
+					    "reserved bw: %s.\n", ret,
+					    str_error(ret));
+				}
+			default:
+				break;
 			}
 			batch->next_step(batch);
Index: uspace/drv/uhci-hcd/hc.h
===================================================================
--- uspace/drv/uhci-hcd/hc.h	(revision 8123695a05edc85df5433b25264e0e8c0cbf18a2)
+++ uspace/drv/uhci-hcd/hc.h	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -43,4 +43,5 @@
 #include <usbhc_iface.h>
 #include <usb/host/device_keeper.h>
+#include <usb/host/bandwidth.h>
 
 #include "batch.h"
@@ -84,4 +85,5 @@
 typedef struct hc {
 	usb_device_keeper_t manager;
+	bandwidth_t bandwidth;
 
 	regs_t *registers;
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 8123695a05edc85df5433b25264e0e8c0cbf18a2)
+++ uspace/drv/uhci-hcd/iface.c	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -128,4 +128,33 @@
 }
 /*----------------------------------------------------------------------------*/
+static int register_endpoint(
+    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	const usb_speed_t speed =
+	    usb_device_keeper_get_speed(&hc->manager, address);
+	size_t size = max_packet_size;
+
+	usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
+	    address, endpoint, usb_str_transfer_type(transfer_type),
+	    usb_str_speed(speed), direction, size, max_packet_size, interval);
+	return bandwidth_reserve(&hc->bandwidth, address, endpoint, direction,
+	    speed, transfer_type, max_packet_size, size, interval);
+}
+/*----------------------------------------------------------------------------*/
+static int unregister_endpoint(
+    ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Unregister endpoint %d:%d %d.\n",
+	    address, endpoint, direction);
+	return bandwidth_release(&hc->bandwidth, address, endpoint, direction);
+}
+/*----------------------------------------------------------------------------*/
 /** Interrupt out transaction interface function
  *
@@ -365,4 +394,7 @@
 	.release_address = release_address,
 
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
 	.interrupt_out = interrupt_out,
 	.interrupt_in = interrupt_in,
Index: uspace/lib/c/generic/adt/hash_table.c
===================================================================
--- uspace/lib/c/generic/adt/hash_table.c	(revision 8123695a05edc85df5433b25264e0e8c0cbf18a2)
+++ uspace/lib/c/generic/adt/hash_table.c	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -54,5 +54,5 @@
  *
  */
-int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
+bool hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
     hash_table_operations_t *op)
 {
Index: uspace/lib/c/include/adt/hash_table.h
===================================================================
--- uspace/lib/c/include/adt/hash_table.h	(revision 8123695a05edc85df5433b25264e0e8c0cbf18a2)
+++ uspace/lib/c/include/adt/hash_table.h	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -38,4 +38,5 @@
 #include <adt/list.h>
 #include <unistd.h>
+#include <bool.h>
 
 typedef unsigned long hash_count_t;
@@ -83,5 +84,5 @@
     list_get_instance((item), type, member)
 
-extern int hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
+extern bool hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
     hash_table_operations_t *);
 extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *);
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 8123695a05edc85df5433b25264e0e8c0cbf18a2)
+++ uspace/lib/usb/Makefile	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -53,5 +53,6 @@
 	src/hidreport.c \
 	src/host/device_keeper.c \
-	src/host/batch.c
+	src/host/batch.c \
+	src/host/bandwidth.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/include/usb/host/bandwidth.h
===================================================================
--- uspace/lib/usb/include/usb/host/bandwidth.h	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
+++ uspace/lib/usb/include/usb/host/bandwidth.h	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -0,0 +1,81 @@
+/*
+ * 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_BANDWIDTH_H
+#define LIBUSB_HOST_BANDWIDTH_H
+
+#include <adt/hash_table.h>
+#include <fibril_synch.h>
+#include <usb/usb.h>
+
+#define BANDWIDTH_TOTAL_USB11 12000000
+#define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9)
+
+typedef struct bandwidth {
+	hash_table_t reserved;
+	fibril_mutex_t guard;
+	size_t free;
+	size_t (*usage_fnc)(usb_speed_t, usb_transfer_type_t, size_t, size_t);
+} bandwidth_t;
+
+size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type,
+    size_t size, size_t max_packet_size);
+
+int bandwidth_init(bandwidth_t *instance, size_t bandwidth,
+    size_t (*usage_fnc)(usb_speed_t, usb_transfer_type_t, size_t, size_t));
+
+void bandwidth_destroy(bandwidth_t *instance);
+
+int bandwidth_reserve(bandwidth_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction, usb_speed_t speed,
+    usb_transfer_type_t transfer_type, size_t max_packet_size, size_t size,
+    unsigned interval);
+
+int bandwidth_release(bandwidth_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction);
+
+int bandwidth_use(bandwidth_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction);
+
+int bandwidth_free(bandwidth_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usb/include/usb/host/device_keeper.h	(revision 8123695a05edc85df5433b25264e0e8c0cbf18a2)
+++ uspace/lib/usb/include/usb/host/device_keeper.h	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -51,5 +51,5 @@
 	usb_speed_t speed;
 	bool occupied;
-	bool control_used;
+	uint16_t control_used;
 	uint16_t toggle_status[2];
 	devman_handle_t handle;
@@ -99,8 +99,8 @@
 
 void usb_device_keeper_use_control(usb_device_keeper_t *instance,
-    usb_address_t address);
+    usb_target_t target);
 
 void usb_device_keeper_release_control(usb_device_keeper_t *instance,
-    usb_address_t address);
+    usb_target_t target);
 
 #endif
Index: uspace/lib/usb/src/host/bandwidth.c
===================================================================
--- uspace/lib/usb/src/host/bandwidth.c	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
+++ uspace/lib/usb/src/host/bandwidth.c	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -0,0 +1,275 @@
+/*
+ * 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.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <usb/host/bandwidth.h>
+
+typedef struct {
+	usb_address_t address;
+	usb_endpoint_t endpoint;
+	usb_direction_t direction;
+} __attribute__((aligned (sizeof(unsigned long)))) transfer_t;
+/*----------------------------------------------------------------------------*/
+typedef struct {
+	transfer_t transfer;
+	link_t link;
+	bool used;
+	size_t required;
+} transfer_status_t;
+/*----------------------------------------------------------------------------*/
+#define BUCKET_COUNT 7
+#define MAX_KEYS (sizeof(transfer_t) / sizeof(unsigned long))
+/*----------------------------------------------------------------------------*/
+static hash_index_t transfer_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 transfer_compare(
+    unsigned long key[], hash_count_t keys, link_t *item)
+{
+	assert(item);
+	transfer_status_t *status =
+	    hash_table_get_instance(item, transfer_status_t, link);
+	const size_t bytes =
+	    keys < MAX_KEYS ? keys * sizeof(unsigned long) : sizeof(transfer_t);
+	return bcmp(key, &status->transfer, bytes);
+}
+/*----------------------------------------------------------------------------*/
+static void transfer_remove(link_t *item)
+{
+	assert(item);
+	transfer_status_t *status =
+	    hash_table_get_instance(item, transfer_status_t, link);
+	assert(status);
+	free(status);
+}
+/*----------------------------------------------------------------------------*/
+hash_table_operations_t op = {
+	.hash = transfer_hash,
+	.compare = transfer_compare,
+	.remove_callback = transfer_remove,
+};
+/*----------------------------------------------------------------------------*/
+size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type,
+    size_t size, size_t max_packet_size)
+{
+	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 bandwidth_init(bandwidth_t *instance, size_t bandwidth,
+    size_t (*usage_fnc)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
+{
+	assert(instance);
+	fibril_mutex_initialize(&instance->guard);
+	instance->free = bandwidth;
+	instance->usage_fnc = usage_fnc;
+	return
+	    hash_table_create(&instance->reserved, BUCKET_COUNT, MAX_KEYS, &op);
+}
+/*----------------------------------------------------------------------------*/
+void bandwidth_destroy(bandwidth_t *instance)
+{
+	hash_table_destroy(&instance->reserved);
+}
+/*----------------------------------------------------------------------------*/
+int bandwidth_reserve(bandwidth_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction, usb_speed_t speed,
+    usb_transfer_type_t transfer_type, size_t max_packet_size, size_t size,
+    unsigned interval)
+{
+	if (transfer_type != USB_TRANSFER_ISOCHRONOUS &&
+	    transfer_type != USB_TRANSFER_INTERRUPT) {
+		return ENOTSUP;
+	}
+
+	assert(instance);
+	assert(instance->usage_fnc);
+
+	transfer_t trans = {
+		.address = address,
+		.endpoint = endpoint,
+		.direction = direction,
+	};
+	fibril_mutex_lock(&instance->guard);
+	const size_t required =
+	    instance->usage_fnc(speed, transfer_type, size, max_packet_size);
+
+	if (required > instance->free) {
+		fibril_mutex_unlock(&instance->guard);
+		return ENOSPC;
+	}
+
+	link_t *item =
+	    hash_table_find(&instance->reserved, (unsigned long*)&trans);
+	if (item != NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return EEXISTS;
+	}
+
+	transfer_status_t *status = malloc(sizeof(transfer_status_t));
+	if (status == NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return ENOMEM;
+	}
+
+	status->transfer = trans;
+	status->required = required;
+	status->used = false;
+	link_initialize(&status->link);
+
+	hash_table_insert(&instance->reserved,
+	    (unsigned long*)&status->transfer, &status->link);
+	instance->free -= required;
+	fibril_mutex_unlock(&instance->guard);
+	return EOK;
+	/* TODO: compute bandwidth used */
+}
+/*----------------------------------------------------------------------------*/
+int bandwidth_release(bandwidth_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(instance);
+	transfer_t trans = {
+		.address = address,
+		.endpoint = endpoint,
+		.direction = direction,
+	};
+	fibril_mutex_lock(&instance->guard);
+	link_t *item =
+	    hash_table_find(&instance->reserved, (unsigned long*)&trans);
+	if (item == NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return EINVAL;
+	}
+
+	transfer_status_t *status =
+	    hash_table_get_instance(item, transfer_status_t, link);
+
+	instance->free += status->required;
+
+	hash_table_remove(&instance->reserved,
+	    (unsigned long*)&trans, MAX_KEYS);
+
+	fibril_mutex_unlock(&instance->guard);
+	return EOK;
+	/* TODO: compute bandwidth freed */
+}
+/*----------------------------------------------------------------------------*/
+int bandwidth_use(bandwidth_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(instance);
+	transfer_t trans = {
+		.address = address,
+		.endpoint = endpoint,
+		.direction = direction,
+	};
+	fibril_mutex_lock(&instance->guard);
+	link_t *item =
+	    hash_table_find(&instance->reserved, (unsigned long*)&trans);
+	int ret = EOK;
+	if (item != NULL) {
+		transfer_status_t *status =
+		    hash_table_get_instance(item, transfer_status_t, link);
+		assert(status);
+		if (status->used) {
+			ret = EINPROGRESS;
+		}
+		status->used = true;
+	} else {
+		ret = EINVAL;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+int bandwidth_free(bandwidth_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(instance);
+	transfer_t trans = {
+		.address = address,
+		.endpoint = endpoint,
+		.direction = direction,
+	};
+	fibril_mutex_lock(&instance->guard);
+	link_t *item =
+	    hash_table_find(&instance->reserved, (unsigned long*)&trans);
+	int ret = EOK;
+	if (item != NULL) {
+		transfer_status_t *status =
+		    hash_table_get_instance(item, transfer_status_t, link);
+		assert(status);
+		if (!status->used) {
+			ret = ENOENT;
+		}
+		status->used = false;
+	} else {
+		ret = EINVAL;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
Index: uspace/lib/usb/src/host/device_keeper.c
===================================================================
--- uspace/lib/usb/src/host/device_keeper.c	(revision 8123695a05edc85df5433b25264e0e8c0cbf18a2)
+++ uspace/lib/usb/src/host/device_keeper.c	(revision 322a8066dd6a2df80d2650aaf0b4e19bbe60b576)
@@ -54,5 +54,5 @@
 	for (; i < USB_ADDRESS_COUNT; ++i) {
 		instance->devices[i].occupied = false;
-		instance->devices[i].control_used = false;
+		instance->devices[i].control_used = 0;
 		instance->devices[i].handle = 0;
 		instance->devices[i].toggle_status[0] = 0;
@@ -311,21 +311,24 @@
 /*----------------------------------------------------------------------------*/
 void usb_device_keeper_use_control(usb_device_keeper_t *instance,
-    usb_address_t address)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	while (instance->devices[address].control_used) {
+    usb_target_t target)
+{
+	assert(instance);
+	const uint16_t ep = 1 << target.endpoint;
+	fibril_mutex_lock(&instance->guard);
+	while (instance->devices[target.address].control_used & ep) {
 		fibril_condvar_wait(&instance->change, &instance->guard);
 	}
-	instance->devices[address].control_used = true;
+	instance->devices[target.address].control_used |= ep;
 	fibril_mutex_unlock(&instance->guard);
 }
 /*----------------------------------------------------------------------------*/
 void usb_device_keeper_release_control(usb_device_keeper_t *instance,
-    usb_address_t address)
-{
-	assert(instance);
-	fibril_mutex_lock(&instance->guard);
-	instance->devices[address].control_used = false;
+    usb_target_t target)
+{
+	assert(instance);
+	const uint16_t ep = 1 << target.endpoint;
+	fibril_mutex_lock(&instance->guard);
+	assert((instance->devices[target.address].control_used & ep) != 0);
+	instance->devices[target.address].control_used &= ~ep;
 	fibril_mutex_unlock(&instance->guard);
 	fibril_condvar_signal(&instance->change);
