Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -33,6 +33,4 @@
  */
 
-#include <adt/hash_table.h>
-#include <adt/hash.h>
 #include <usb/host/utils/malloc32.h>
 #include <usb/host/ddf_helpers.h>
@@ -50,16 +48,4 @@
 #include "endpoint.h"
 #include "transfers.h"
-
-/** Element of the hash table. */
-typedef struct {
-	ht_link_t link;
-
-	/** Device */
-	xhci_device_t *device;
-} hashed_device_t;
-
-static int hashed_device_insert(xhci_bus_t *bus, hashed_device_t **hashed_dev, xhci_device_t *dev);
-static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev);
-static int hashed_device_find_by_address(xhci_bus_t *bus, usb_address_t address, hashed_device_t **dev);
 
 /** TODO: Still some copy-pasta left...
@@ -94,19 +80,12 @@
 	bus->devices_by_slot[xhci_dev->slot_id] = xhci_dev;
 
-	hashed_device_t *hashed_dev = NULL;
-	if ((err = hashed_device_insert(bus, &hashed_dev, xhci_dev)))
-		goto err_address;
-
 	/* Read the device descriptor, derive the match ids */
 	if ((err = hcd_ddf_device_explore(hc->hcd, dev))) {
 		usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err));
-		goto err_hash;
-	}
-
-	return EOK;
-
-err_hash:
-	bus->devices_by_slot[xhci_dev->slot_id] = NULL;
-	hashed_device_remove(bus, hashed_dev);
+		goto err_address;
+	}
+
+	return EOK;
+
 err_address:
 	bus_release_address(&bus->base, dev->address);
@@ -127,13 +106,4 @@
 	}
 
-	hashed_device_t *hashed_dev;
-	int res = hashed_device_find_by_address(bus, dev->address, &hashed_dev);
-	if (res)
-		return res;
-
-	res = hashed_device_remove(bus, hashed_dev);
-	if (res != EOK)
-		return res;
-
 	// XXX: Ugly here. Move to device_destroy at endpoint.c?
 	free32(xhci_dev->dev_ctx);
@@ -193,54 +163,4 @@
 	xhci_endpoint_fini(xhci_ep);
 	free(xhci_ep);
-}
-
-static int hashed_device_find_by_address(xhci_bus_t *bus, usb_address_t address, hashed_device_t **dev)
-{
-	ht_link_t *link = hash_table_find(&bus->devices, &address);
-	if (link == NULL)
-		return ENOENT;
-
-	*dev = hash_table_get_inst(link, hashed_device_t, link);
-	return EOK;
-}
-
-static int xhci_endpoint_find_by_target(xhci_bus_t *bus, usb_target_t target, xhci_endpoint_t **ep)
-{
-	hashed_device_t *dev;
-	int res = hashed_device_find_by_address(bus, target.address, &dev);
-	if (res != EOK)
-		return res;
-
-	xhci_endpoint_t *ret_ep = xhci_device_get_endpoint(dev->device, target.endpoint);
-	if (!ret_ep)
-		return ENOENT;
-
-	*ep = ret_ep;
-	return EOK;
-}
-
-static int hashed_device_insert(xhci_bus_t *bus, hashed_device_t **hashed_dev, xhci_device_t *dev)
-{
-	hashed_device_t *ret_dev = (hashed_device_t *) calloc(1, sizeof(hashed_device_t));
-	if (!ret_dev)
-		return ENOMEM;
-
-	ret_dev->device = dev;
-
-	usb_log_info("Device(%d) registered to XHCI bus.", dev->base.address);
-
-	hash_table_insert(&bus->devices, &ret_dev->link);
-	*hashed_dev = ret_dev;
-	return EOK;
-}
-
-static int hashed_device_remove(xhci_bus_t *bus, hashed_device_t *hashed_dev)
-{
-	usb_log_info("Device(%d) released from XHCI bus.", hashed_dev->device->base.address);
-
-	hash_table_remove(&bus->devices, &hashed_dev->device->base.address);
-	free(hashed_dev);
-
-	return EOK;
 }
 
@@ -273,12 +193,10 @@
 }
 
-static endpoint_t* find_endpoint(bus_t *bus_base, usb_target_t target, usb_direction_t direction)
-{
-	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
-	assert(bus);
-
-	xhci_endpoint_t *ep;
-	int res = xhci_endpoint_find_by_target(bus, target, &ep);
-	if (res != EOK)
+static endpoint_t* find_endpoint(bus_t *bus_base, device_t *dev_base, usb_target_t target, usb_direction_t direction)
+{
+	xhci_device_t *dev = xhci_device_get(dev_base);
+
+	xhci_endpoint_t *ep = xhci_device_get_endpoint(dev, target.endpoint);
+	if (!ep)
 		return NULL;
 
@@ -345,30 +263,4 @@
 };
 
-static size_t device_ht_hash(const ht_link_t *item)
-{
-	hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link);
-	return (size_t) hash_mix(dev->device->base.address);
-}
-
-static size_t device_ht_key_hash(void *key)
-{
-	return (size_t) hash_mix(*(usb_address_t *)key);
-}
-
-static bool device_ht_key_equal(void *key, const ht_link_t *item)
-{
-	hashed_device_t *dev = hash_table_get_inst(item, hashed_device_t, link);
-	return dev->device->base.address == *(usb_address_t *) key;
-}
-
-/** Operations for the device hash table. */
-static hash_table_ops_t device_ht_ops = {
-	.hash = device_ht_hash,
-	.key_hash = device_ht_key_hash,
-	.key_equal = device_ht_key_equal,
-	.equal = NULL,
-	.remove_callback = NULL
-};
-
 int xhci_bus_init(xhci_bus_t *bus, xhci_hc_t *hc)
 {
@@ -381,9 +273,4 @@
 		return ENOMEM;
 
-	if (!hash_table_create(&bus->devices, 0, 0, &device_ht_ops)) {
-		free(bus->devices_by_slot);
-		return ENOMEM;
-	}
-
 	bus->base.ops = xhci_bus_ops;
 	return EOK;
@@ -392,7 +279,5 @@
 void xhci_bus_fini(xhci_bus_t *bus)
 {
-	// FIXME: Make sure no devices are in the hash table.
-
-	hash_table_destroy(&bus->devices);
+
 }
 
Index: uspace/drv/bus/usb/xhci/bus.h
===================================================================
--- uspace/drv/bus/usb/xhci/bus.h	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/drv/bus/usb/xhci/bus.h	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -38,5 +38,4 @@
 #define XHCI_BUS_H
 
-#include <adt/hash_table.h>
 #include <usb/usb.h>
 #include <usb/host/bus.h>
@@ -50,7 +49,4 @@
 
 	xhci_device_t **devices_by_slot;	/**< Devices by Slot ID */
-
-	/** TODO: Do we really need this? */
-	hash_table_t devices;		/**< Devices by address */
 } xhci_bus_t;
 
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/drv/Makefile	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -33,4 +33,5 @@
 	-Igeneric/private \
 	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
 	-I$(LIBPCM_PREFIX)/include
 LIBRARY = libdrv
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/drv/generic/remote_usb.c	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -38,4 +38,5 @@
 #include <errno.h>
 #include <devman.h>
+#include <usb/host/usb_transfer_batch.h>
 
 #include "usb_iface.h"
@@ -539,34 +540,31 @@
 }
 
-static void callback_out(int outcome, void *arg)
-{
-	async_transaction_t *trans = arg;
-
-	async_answer_0(trans->caller, outcome);
+static int callback_out(usb_transfer_batch_t *batch)
+{
+	async_transaction_t *trans = batch->on_complete_data;
+
+	const int err = async_answer_0(trans->caller, batch->error);
 
 	async_transaction_destroy(trans);
-}
-
-static void callback_in(int outcome, size_t actual_size, void *arg)
-{
-	async_transaction_t *trans = (async_transaction_t *)arg;
-
-	if (outcome != EOK) {
-		async_answer_0(trans->caller, outcome);
-		if (trans->data_caller) {
+
+	return err;
+}
+
+static int callback_in(usb_transfer_batch_t *batch)
+{
+	async_transaction_t *trans = batch->on_complete_data;
+
+	if (trans->data_caller) {
+		if (batch->error == EOK) {
+			batch->error = async_data_read_finalize(trans->data_caller,
+			    trans->buffer, batch->transfered_size);
+		} else {
 			async_answer_0(trans->data_caller, EINTR);
 		}
-		async_transaction_destroy(trans);
-		return;
-	}
-
-	if (trans->data_caller) {
-		async_data_read_finalize(trans->data_caller,
-		    trans->buffer, actual_size);
-	}
-
-	async_answer_0(trans->caller, EOK);
-
+	}
+
+	const int err = async_answer_0(trans->caller, batch->error);
 	async_transaction_destroy(trans);
+	return err;
 }
 
@@ -611,6 +609,11 @@
 	}
 
+	const usb_target_t target = {{
+		/* .address is initialized by read itself */
+		.endpoint = ep,
+	}};
+
 	const int rc = usb_iface->read(
-	    fun, ep, setup, trans->buffer, size, callback_in, trans);
+	    fun, target, setup, trans->buffer, size, callback_in, trans);
 
 	if (rc != EOK) {
@@ -659,6 +662,11 @@
 	}
 
+	const usb_target_t target = {{
+		/* .address is initialized by write itself */
+		.endpoint = ep,
+	}};
+
 	const int rc = usb_iface->write(
-	    fun, ep, setup, trans->buffer, size, callback_out, trans);
+	    fun, target, setup, trans->buffer, size, callback_out, trans);
 
 	if (rc != EOK) {
Index: uspace/lib/drv/include/usb_iface.h
===================================================================
--- uspace/lib/drv/include/usb_iface.h	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/drv/include/usb_iface.h	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -64,9 +64,9 @@
     size_t);
 
-/** Callback for outgoing transfer. */
-typedef void (*usb_iface_transfer_out_callback_t)(int, void *);
+/** Defined in usb/host/usb_transfer_batch.h */
+typedef struct usb_transfer_batch usb_transfer_batch_t;
 
-/** Callback for incoming transfer. */
-typedef void (*usb_iface_transfer_in_callback_t)(int, size_t, void *);
+/** Callback for outgoing transfer - clone of usb_transfer_batch_callback_t */
+typedef int (*usb_iface_transfer_callback_t)(usb_transfer_batch_t *);
 
 /** USB device communication interface. */
@@ -84,8 +84,10 @@
 	int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_desc_t *);
 
-	int (*read)(ddf_fun_t *, usb_endpoint_t, uint64_t, uint8_t *, size_t,
-	    usb_iface_transfer_in_callback_t, void *);
-	int (*write)(ddf_fun_t *, usb_endpoint_t, uint64_t, const uint8_t *,
-	    size_t, usb_iface_transfer_out_callback_t, void *);
+	int (*read)(ddf_fun_t *, usb_target_t,
+		uint64_t, char *, size_t,
+		usb_iface_transfer_callback_t, void *);
+	int (*write)(ddf_fun_t *, usb_target_t,
+		uint64_t, const char *, size_t,
+		usb_iface_transfer_callback_t, void *);
 } usb_iface_t;
 
Index: uspace/lib/usbhost/include/usb/host/bus.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/bus.h	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/include/usb/host/bus.h	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -85,5 +85,5 @@
 	int (*register_endpoint)(bus_t *, endpoint_t *);
 	int (*unregister_endpoint)(bus_t *, endpoint_t *);
-	endpoint_t *(*find_endpoint)(bus_t *, usb_target_t, usb_direction_t);
+	endpoint_t *(*find_endpoint)(bus_t *, device_t*, usb_target_t, usb_direction_t);
 	void (*destroy_endpoint)(endpoint_t *);			/**< Optional */
 	bool (*endpoint_get_toggle)(endpoint_t *);		/**< Optional */
@@ -120,5 +120,5 @@
     usb_direction_t dir, usb_transfer_type_t type, size_t max_packet_size,
     unsigned packets, size_t size);
-extern int bus_remove_ep(bus_t *bus, usb_target_t target, usb_direction_t dir);
+extern int bus_remove_ep(bus_t *, device_t *, usb_target_t, usb_direction_t);
 
 int device_set_default_name(device_t *);
@@ -130,5 +130,5 @@
 int bus_register_endpoint(bus_t *, endpoint_t *);
 int bus_unregister_endpoint(bus_t *, endpoint_t *);
-endpoint_t *bus_find_endpoint(bus_t *, usb_target_t, usb_direction_t);
+endpoint_t *bus_find_endpoint(bus_t *, device_t *, usb_target_t, usb_direction_t);
 
 size_t bus_count_bw(endpoint_t *, size_t);
Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -108,10 +108,11 @@
 extern int hcd_remove_ep(hcd_t *, usb_target_t, usb_direction_t);
 
-extern int hcd_send_batch(hcd_t *, usb_target_t, usb_direction_t, void *,
-    size_t, uint64_t, usbhc_iface_transfer_in_callback_t,
-    usbhc_iface_transfer_out_callback_t, void *, const char *);
+extern int hcd_send_batch(hcd_t *, device_t *, usb_target_t,
+    usb_direction_t direction, char *, size_t, uint64_t,
+    usb_transfer_batch_callback_t, void *, const char *);
 
-extern ssize_t hcd_send_batch_sync(hcd_t *, usb_target_t, usb_direction_t,
-    void *, size_t, uint64_t, const char *);
+extern ssize_t hcd_send_batch_sync(hcd_t *, device_t *, usb_target_t,
+    usb_direction_t direction, char *, size_t, uint64_t,
+    const char *);
 
 #endif
Index: uspace/lib/usbhost/include/usb/host/usb2_bus.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb2_bus.h	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/include/usb/host/usb2_bus.h	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -56,4 +56,5 @@
 		usb_speed_t speed;      /**< Device speed */
 		bool occupied;          /**< The address is in use. */
+		// TODO: This can be stored in usb2_bus-specific device_t
 		list_t endpoint_list;   /**< Store endpoint_t instances */
 	} devices[USB_ADDRESS_COUNT];
Index: uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -108,10 +108,4 @@
 void usb_transfer_batch_destroy(usb_transfer_batch_t *);
 
-/** Provided to ease the transition. Wraps old-style handlers into a new one.
- */
-extern void usb_transfer_batch_set_old_handlers(usb_transfer_batch_t *,
-	usbhc_iface_transfer_in_callback_t,
-	usbhc_iface_transfer_out_callback_t, void *);
-
 #endif
 
Index: uspace/lib/usbhost/src/bus.c
===================================================================
--- uspace/lib/usbhost/src/bus.c	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/src/bus.c	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -99,8 +99,8 @@
 }
 
-int bus_remove_ep(bus_t *bus, usb_target_t target, usb_direction_t dir)
-{
-	assert(bus);
-	endpoint_t *ep = bus_find_endpoint(bus, target, dir);
+int bus_remove_ep(bus_t *bus, device_t *dev, usb_target_t target, usb_direction_t dir)
+{
+	assert(bus);
+	endpoint_t *ep = bus_find_endpoint(bus, dev, target, dir);
 	if (!ep)
 		return ENOENT;
@@ -200,10 +200,10 @@
 /** Searches for an endpoint. Returns a reference.
  */
-endpoint_t *bus_find_endpoint(bus_t *bus, usb_target_t target, usb_direction_t dir)
-{
-	assert(bus);
-
-	fibril_mutex_lock(&bus->guard);
-	endpoint_t *ep = bus->ops.find_endpoint(bus, target, dir);
+endpoint_t *bus_find_endpoint(bus_t *bus, device_t *device, usb_target_t endpoint, usb_direction_t dir)
+{
+	assert(bus);
+
+	fibril_mutex_lock(&bus->guard);
+	endpoint_t *ep = bus->ops.find_endpoint(bus, device, endpoint, dir);
 	if (ep) {
 		/* Exporting reference */
Index: uspace/lib/usbhost/src/ddf_helpers.c
===================================================================
--- uspace/lib/usbhost/src/ddf_helpers.c	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/src/ddf_helpers.c	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -135,5 +135,5 @@
 		dev->address, endpoint_desc->endpoint_no,
 		usb_str_direction(endpoint_desc->direction));
-	return bus_remove_ep(hcd->bus, target, endpoint_desc->direction);
+	return bus_remove_ep(hcd->bus, dev, target, endpoint_desc->direction);
 }
 
@@ -216,18 +216,18 @@
  * @return Error code.
  */
-static int dev_read(ddf_fun_t *fun, usb_endpoint_t endpoint,
-    uint64_t setup_data, uint8_t *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
+static int dev_read(ddf_fun_t *fun, usb_target_t target,
+    uint64_t setup_data, char *data, size_t size,
+    usb_iface_transfer_callback_t callback, void *arg)
 {
 	assert(fun);
+	hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
 	device_t *dev = ddf_fun_data_get(fun);
 	assert(dev);
-	const usb_target_t target = {{
-	    .address  = dev->address,
-	    .endpoint = endpoint,
-	}};
-	return hcd_send_batch(dev_to_hcd(ddf_fun_get_dev(fun)), target,
-	    USB_DIRECTION_IN, data, size, setup_data, callback, NULL, arg,
-	    "READ");
+
+	target.address = dev->address;
+
+	return hcd_send_batch(hcd, dev, target, USB_DIRECTION_IN,
+	    data, size, setup_data,
+	    callback, arg, "READ");
 }
 
@@ -242,17 +242,17 @@
  * @return Error code.
  */
-static int dev_write(ddf_fun_t *fun, usb_endpoint_t endpoint,
-    uint64_t setup_data, const uint8_t *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
+static int dev_write(ddf_fun_t *fun, usb_target_t target,
+    uint64_t setup_data, const char *data, size_t size,
+    usb_iface_transfer_callback_t callback, void *arg)
 {
 	assert(fun);
+	hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));
 	device_t *dev = ddf_fun_data_get(fun);
 	assert(dev);
-	const usb_target_t target = {{
-	    .address  = dev->address,
-	    .endpoint = endpoint,
-	}};
-	return hcd_send_batch(dev_to_hcd(ddf_fun_get_dev(fun)),
-	    target, USB_DIRECTION_OUT, (uint8_t*)data, size, setup_data, NULL,
+
+	target.address = dev->address;
+
+	return hcd_send_batch(hcd, dev, target, USB_DIRECTION_OUT,
+	    (char *) data, size, setup_data,
 	    callback, arg, "WRITE");
 }
@@ -411,7 +411,7 @@
 	init_match_ids(&mids);
 
-	usb_target_t control_ep = {{
+	const usb_target_t control_ep = {{
 		.address = device->address,
-		.endpoint = 0
+		.endpoint = 0,
 	}};
 
@@ -422,6 +422,6 @@
 	usb_log_debug("Device(%d): Requesting full device descriptor.",
 	    device->address);
-	ssize_t got = hcd_send_batch_sync(hcd, control_ep, USB_DIRECTION_IN,
-	    &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
+	ssize_t got = hcd_send_batch_sync(hcd, device, control_ep, USB_DIRECTION_IN,
+	    (char *) &desc, sizeof(desc), *(uint64_t *)&get_device_desc,
 	    "read device descriptor");
 	if (got < 0) {
Index: uspace/lib/usbhost/src/hcd.c
===================================================================
--- uspace/lib/usbhost/src/hcd.c	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/src/hcd.c	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -80,15 +80,15 @@
  * @return Error code.
  */
-int hcd_send_batch(hcd_t *hcd, usb_target_t target, usb_direction_t direction,
-	void *data, size_t size, uint64_t setup_data,
-	usbhc_iface_transfer_in_callback_t in, usbhc_iface_transfer_out_callback_t out,
-	void *arg, const char *name)
+int hcd_send_batch(hcd_t *hcd, device_t *device, usb_target_t target,
+    usb_direction_t direction, char *data, size_t size, uint64_t setup_data,
+    usb_transfer_batch_callback_t on_complete, void *arg, const char *name)
 {
 	assert(hcd);
+	assert(device->address == target.address);
 
-	endpoint_t *ep = bus_find_endpoint(hcd->bus, target, direction);
+	endpoint_t *ep = bus_find_endpoint(hcd->bus, device, target, direction);
 	if (ep == NULL) {
 		usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
-		    target.address, target.endpoint, name);
+		    device->address, target.endpoint, name);
 		return ENOENT;
 	}
@@ -120,4 +120,6 @@
 	batch->setup.packed = setup_data;
 	batch->dir = direction;
+	batch->on_complete = on_complete;
+	batch->on_complete_data = arg;
 
 	/* Check for commands that reset toggle bit */
@@ -125,6 +127,4 @@
 		batch->toggle_reset_mode
 			= usb_request_get_toggle_reset_mode(&batch->setup.packet);
-
-	usb_transfer_batch_set_old_handlers(batch, in, out, arg);
 
 	const int ret = hcd->ops.schedule(hcd, batch);
@@ -144,44 +144,34 @@
 	fibril_condvar_t done_cv;
 	unsigned done;
-	int ret;
-	size_t size;
+
+	size_t transfered_size;
+	int error;
 } sync_data_t;
 
-static void transfer_in_cb(int ret, size_t size, void* data)
+static int sync_transfer_complete(usb_transfer_batch_t *batch)
 {
-	sync_data_t *d = data;
+	sync_data_t *d = batch->on_complete_data;
 	assert(d);
-	d->ret = ret;
-	d->size = size;
+	d->transfered_size = batch->transfered_size;
+	d->error = batch->error;
 	fibril_mutex_lock(&d->done_mtx);
 	d->done = 1;
 	fibril_condvar_broadcast(&d->done_cv);
 	fibril_mutex_unlock(&d->done_mtx);
+	return EOK;
 }
 
-static void transfer_out_cb(int ret, void* data)
-{
-	sync_data_t *d = data;
-	assert(data);
-	d->ret = ret;
-	fibril_mutex_lock(&d->done_mtx);
-	d->done = 1;
-	fibril_condvar_broadcast(&d->done_cv);
-	fibril_mutex_unlock(&d->done_mtx);
-}
-
-/** this is really ugly version of sync usb communication */
-ssize_t hcd_send_batch_sync(
-    hcd_t *hcd, usb_target_t target, usb_direction_t dir,
-    void *data, size_t size, uint64_t setup_data, const char* name)
+ssize_t hcd_send_batch_sync(hcd_t *hcd, device_t *device, usb_target_t target,
+    usb_direction_t direction, char *data, size_t size, uint64_t setup_data,
+    const char *name)
 {
 	assert(hcd);
-	sync_data_t sd = { .done = 0, .ret = EBUSY, .size = size };
+	sync_data_t sd = { .done = 0 };
 	fibril_mutex_initialize(&sd.done_mtx);
 	fibril_condvar_initialize(&sd.done_cv);
 
-	const int ret = hcd_send_batch(hcd, target, dir, data, size, setup_data,
-	    dir == USB_DIRECTION_IN ? transfer_in_cb : NULL,
-	    dir == USB_DIRECTION_OUT ? transfer_out_cb : NULL, &sd, name);
+	const int ret = hcd_send_batch(hcd, device, target, direction,
+	    data, size, setup_data,
+	    sync_transfer_complete, &sd, name);
 	if (ret != EOK)
 		return ret;
@@ -192,7 +182,7 @@
 	fibril_mutex_unlock(&sd.done_mtx);
 
-	if (sd.ret == EOK)
-		return sd.size;
-	return sd.ret;
+	return (sd.error == EOK)
+		? (ssize_t) sd.transfered_size
+		: (ssize_t) sd.error;
 }
 
Index: uspace/lib/usbhost/src/usb2_bus.c
===================================================================
--- uspace/lib/usbhost/src/usb2_bus.c	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/src/usb2_bus.c	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -126,6 +126,6 @@
 	usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
 	    address);
-	ssize_t got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
-	    &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
+	ssize_t got = hcd_send_batch_sync(hcd, dev, default_target, USB_DIRECTION_IN,
+	    (char *) &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
 	    "read first 8 bytes of dev descriptor");
 
@@ -141,5 +141,5 @@
 
 	usb_log_debug("Device(%d): Setting USB address.", address);
-	err = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
+	err = hcd_send_batch_sync(hcd, dev, default_target, USB_DIRECTION_OUT,
 	    NULL, 0, *(uint64_t *)&set_address, "set address");
 	if (err != 0) {
@@ -163,9 +163,9 @@
 	}
 
-	bus_remove_ep(bus, default_target, USB_DIRECTION_BOTH);
+	bus_remove_ep(bus, dev, default_target, USB_DIRECTION_BOTH);
 	return EOK;
 
 err_default_target:
-	bus_remove_ep(bus, default_target, USB_DIRECTION_BOTH);
+	bus_remove_ep(bus, dev, default_target, USB_DIRECTION_BOTH);
 err_address:
 	bus_release_address(bus, address);
@@ -247,5 +247,5 @@
  * @note Assumes that the internal mutex is locked.
  */
-static endpoint_t *usb2_bus_find_ep(bus_t *bus_base, usb_target_t target, usb_direction_t direction)
+static endpoint_t *usb2_bus_find_ep(bus_t *bus_base, device_t *device, usb_target_t target, usb_direction_t direction)
 {
 	usb2_bus_t *bus = bus_to_usb2_bus(bus_base);
@@ -293,5 +293,5 @@
 
 	/* Check for existence */
-	if (usb2_bus_find_ep(bus_base, ep->target, ep->direction))
+	if (usb2_bus_find_ep(bus_base, ep->device, ep->target, ep->direction))
 		return EEXIST;
 
Index: uspace/lib/usbhost/src/usb_transfer_batch.c
===================================================================
--- uspace/lib/usbhost/src/usb_transfer_batch.c	(revision e160bfe8a5d875ff061225e5b3e77814211c6bff)
+++ uspace/lib/usbhost/src/usb_transfer_batch.c	(revision 327f14759b992c17c88f75a6ddd0e2aa077e1957)
@@ -133,43 +133,4 @@
 }
 
-
-struct old_handler_wrapper_data {
-	usbhc_iface_transfer_in_callback_t in_callback;
-	usbhc_iface_transfer_out_callback_t out_callback;
-	void *arg;
-};
-
-static int old_handler_wrapper(usb_transfer_batch_t *batch)
-{
-	struct old_handler_wrapper_data *data = batch->on_complete_data;
-
-	assert(data);
-
-	if (data->out_callback)
-		data->out_callback(batch->error, data->arg);
-
-	if (data->in_callback)
-		data->in_callback(batch->error, batch->transfered_size, data->arg);
-
-	free(data);
-	return EOK;
-}
-
-void usb_transfer_batch_set_old_handlers(usb_transfer_batch_t *batch,
-	usbhc_iface_transfer_in_callback_t in_callback,
-	usbhc_iface_transfer_out_callback_t out_callback,
-	void *arg)
-{
-	struct old_handler_wrapper_data *data = malloc(sizeof(*data));
-
-	assert((!in_callback) != (!out_callback));
-
-	data->in_callback = in_callback;
-	data->out_callback = out_callback;
-	data->arg = arg;
-
-	batch->on_complete = old_handler_wrapper;
-	batch->on_complete_data = data;
-}
 /**
  * @}
