Index: uspace/lib/usbhost/src/endpoint.c
===================================================================
--- uspace/lib/usbhost/src/endpoint.c	(revision 2833bb4cbd3b1df768dce926e9942633366f6b10)
+++ uspace/lib/usbhost/src/endpoint.c	(revision 726af2943d55d771d5aa19f5caa200059d40ff8a)
@@ -121,6 +121,4 @@
 }
 
-static void endpoint_toggle_reset(endpoint_t *ep, toggle_reset_mode_t mode);
-
 /**
  * Wait until the endpoint have no transfer scheduled.
@@ -166,40 +164,6 @@
 	assert(ep);
 	assert(fibril_mutex_is_locked(&ep->guard));
-
-	if (ep->active_batch && ep->active_batch->error == EOK)
-		endpoint_toggle_reset(ep, ep->active_batch->toggle_reset_mode);
-
 	ep->active_batch = NULL;
 	fibril_condvar_signal(&ep->avail);
-}
-
-/**
- * The transfer on an endpoint can trigger a reset of the toggle bit. This
- * function calls the respective bus callbacks to resolve it.
- *
- * @param ep The endpoint that triggered the reset
- * @param mode Whether to reset no, one or all endpoints on a device.
- */
-static void endpoint_toggle_reset(endpoint_t *ep, toggle_reset_mode_t mode)
-{
-	assert(ep);
-
-	if (mode == RESET_NONE)
-		return;
-
-	const bus_ops_t *ops = BUS_OPS_LOOKUP(get_bus_ops(ep), endpoint_toggle_reset);
-	if (!ops)
-		return;
-
-
-	if (mode == RESET_ALL) {
-		const device_t *dev = ep->device;
-		for (usb_endpoint_t i = 0; i < USB_ENDPOINT_MAX; ++i) {
-			if (dev->endpoints[i])
-				ops->endpoint_toggle_reset(dev->endpoints[i]);
-		}
-	} else {
-		ops->endpoint_toggle_reset(ep);
-	}
 }
 
@@ -282,9 +246,4 @@
 	batch->on_complete_data = arg;
 
-	/* Check for commands that reset toggle bit */
-	if (ep->transfer_type == USB_TRANSFER_CONTROL)
-		batch->toggle_reset_mode
-			= hc_get_request_toggle_reset_mode(&batch->setup.packet);
-
 	const int ret = ops->batch_schedule(batch);
 	if (ret != EOK) {
Index: uspace/lib/usbhost/src/utility.c
===================================================================
--- uspace/lib/usbhost/src/utility.c	(revision 2833bb4cbd3b1df768dce926e9942633366f6b10)
+++ uspace/lib/usbhost/src/utility.c	(revision 726af2943d55d771d5aa19f5caa200059d40ff8a)
@@ -37,4 +37,5 @@
 #include <usb/debug.h>
 #include <usb/descriptor.h>
+#include <usb/request.h>
 
 #include "ddf_helpers.h"
@@ -101,16 +102,133 @@
 }
 
-/** Check setup packet data for signs of toggle reset.
- *
- * @param[in] requst Setup requst data.
- *
- * @retval -1 No endpoints need reset.
- * @retval 0 All endpoints need reset.
- * @retval >0 Specified endpoint needs reset.
- *
- */
-toggle_reset_mode_t hc_get_request_toggle_reset_mode(const usb_device_request_setup_packet_t *request)
-{
-	assert(request);
+int hc_get_device_desc(device_t *device, usb_standard_device_descriptor_t *desc)
+{
+	const usb_target_t control_ep = {{
+		.address = device->address,
+		.endpoint = 0,
+	}};
+
+	/* Get std device descriptor */
+	const usb_device_request_setup_packet_t get_device_desc =
+	    GET_DEVICE_DESC(sizeof(*desc));
+
+	usb_log_debug("Device(%d): Requesting full device descriptor.",
+	    device->address);
+	ssize_t got = bus_device_send_batch_sync(device, control_ep, USB_DIRECTION_IN,
+	    (char *) desc, sizeof(*desc), *(uint64_t *)&get_device_desc,
+	    "read device descriptor");
+
+	if (got < 0)
+		return got;
+
+	return got == sizeof(*desc) ? EOK : EOVERFLOW;
+}
+
+int hc_get_hub_desc(device_t *device, usb_hub_descriptor_header_t *desc)
+{
+	const usb_target_t control_ep = {{
+		.address = device->address,
+		.endpoint = 0,
+	}};
+
+	const usb_device_request_setup_packet_t get_hub_desc = {
+		.request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST
+		    | (USB_REQUEST_TYPE_CLASS << 5)
+		    | USB_REQUEST_RECIPIENT_DEVICE,
+		.request = USB_DEVREQ_GET_DESCRIPTOR, \
+		.value = uint16_host2usb(USB_DESCTYPE_HUB << 8), \
+		.length = sizeof(*desc),
+	};
+
+	usb_log_debug("Device(%d): Requesting hub descriptor.",
+	    device->address);
+	ssize_t got = bus_device_send_batch_sync(device, control_ep, USB_DIRECTION_IN,
+	    (char *) desc, sizeof(*desc), *(uint64_t *)&get_hub_desc,
+	    "get hub descriptor");
+
+	if (got < 0)
+		return got;
+
+	return got == sizeof(*desc) ? EOK : EOVERFLOW;
+}
+
+int hc_device_explore(device_t *device)
+{
+	int err;
+	usb_standard_device_descriptor_t desc = { 0 };
+
+	if ((err = hc_get_device_desc(device, &desc))) {
+		usb_log_error("Device(%d): Failed to get dev descriptor: %s",
+		    device->address, str_error(err));
+		return err;
+	}
+
+	if ((err = hcd_ddf_setup_match_ids(device, &desc))) {
+		usb_log_error("Device(%d): Failed to setup match ids: %s", device->address, str_error(err));
+		return err;
+	}
+
+	return EOK;
+}
+
+/** Announce root hub to the DDF
+ *
+ * @param[in] device Host controller ddf device
+ * @return Error code
+ */
+int hc_setup_virtual_root_hub(hc_device_t *hcd)
+{
+	int err;
+
+	assert(hcd);
+
+	device_t *dev = hcd_ddf_fun_create(hcd, USB_SPEED_MAX);
+	if (!dev) {
+		usb_log_error("Failed to create function for the root hub.");
+		return ENOMEM;
+	}
+
+	ddf_fun_set_name(dev->fun, "roothub");
+
+	/* Assign an address to the device */
+	if ((err = bus_device_enumerate(dev))) {
+		usb_log_error("Failed to enumerate roothub device: %s", str_error(err));
+		goto err_usb_dev;
+	}
+
+	if ((err = ddf_fun_bind(dev->fun))) {
+		usb_log_error("Failed to register roothub: %s.", str_error(err));
+		goto err_enumerated;
+	}
+
+	return EOK;
+
+err_enumerated:
+	bus_device_gone(dev);
+err_usb_dev:
+	hcd_ddf_fun_destroy(dev);
+	return err;
+}
+
+/** How many toggles need to be reset */
+typedef enum {
+	RESET_NONE,
+	RESET_EP,
+	RESET_ALL
+} toggle_reset_mode_t;
+
+/**
+ * Check setup packet data for signs of toggle reset.
+ *
+ * @param[in] batch USB batch
+ */
+static toggle_reset_mode_t get_request_toggle_reset_mode(const usb_transfer_batch_t *batch)
+{
+	if (batch->ep->transfer_type != USB_TRANSFER_CONTROL
+	    || batch->dir != USB_DIRECTION_OUT)
+		return RESET_NONE;
+
+	const usb_device_request_setup_packet_t *request = &batch->setup.packet;
+
 	switch (request->request)
 	{
@@ -139,111 +257,27 @@
 }
 
-int hc_get_device_desc(device_t *device, usb_standard_device_descriptor_t *desc)
-{
-	const usb_target_t control_ep = {{
-		.address = device->address,
-		.endpoint = 0,
-	}};
-
-	/* Get std device descriptor */
-	const usb_device_request_setup_packet_t get_device_desc =
-	    GET_DEVICE_DESC(sizeof(*desc));
-
-	usb_log_debug("Device(%d): Requesting full device descriptor.",
-	    device->address);
-	ssize_t got = bus_device_send_batch_sync(device, control_ep, USB_DIRECTION_IN,
-	    (char *) desc, sizeof(*desc), *(uint64_t *)&get_device_desc,
-	    "read device descriptor");
-
-	if (got < 0)
-		return got;
-
-	return got == sizeof(*desc) ? EOK : EOVERFLOW;
-}
-
-int hc_get_hub_desc(device_t *device, usb_hub_descriptor_header_t *desc)
-{
-	const usb_target_t control_ep = {{
-		.address = device->address,
-		.endpoint = 0,
-	}};
-
-	const usb_device_request_setup_packet_t get_hub_desc = {
-		.request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST
-		    | (USB_REQUEST_TYPE_CLASS << 5)
-		    | USB_REQUEST_RECIPIENT_DEVICE,
-		.request = USB_DEVREQ_GET_DESCRIPTOR, \
-		.value = uint16_host2usb(USB_DESCTYPE_HUB << 8), \
-		.length = sizeof(*desc),
-	};
-
-	usb_log_debug("Device(%d): Requesting hub descriptor.",
-	    device->address);
-	ssize_t got = bus_device_send_batch_sync(device, control_ep, USB_DIRECTION_IN,
-	    (char *) desc, sizeof(*desc), *(uint64_t *)&get_hub_desc,
-	    "get hub descriptor");
-
-	if (got < 0)
-		return got;
-
-	return got == sizeof(*desc) ? EOK : EOVERFLOW;
-}
-
-int hc_device_explore(device_t *device)
-{
-	int err;
-	usb_standard_device_descriptor_t desc = { 0 };
-
-	if ((err = hc_get_device_desc(device, &desc))) {
-		usb_log_error("Device(%d): Failed to get dev descriptor: %s",
-		    device->address, str_error(err));
-		return err;
-	}
-
-	if ((err = hcd_ddf_setup_match_ids(device, &desc))) {
-		usb_log_error("Device(%d): Failed to setup match ids: %s", device->address, str_error(err));
-		return err;
-	}
-
-	return EOK;
-}
-
-/** Announce root hub to the DDF
- *
- * @param[in] device Host controller ddf device
- * @return Error code
- */
-int hc_setup_virtual_root_hub(hc_device_t *hcd)
-{
-	int err;
-
-	assert(hcd);
-
-	device_t *dev = hcd_ddf_fun_create(hcd, USB_SPEED_MAX);
-	if (!dev) {
-		usb_log_error("Failed to create function for the root hub.");
-		return ENOMEM;
-	}
-
-	ddf_fun_set_name(dev->fun, "roothub");
-
-	/* Assign an address to the device */
-	if ((err = bus_device_enumerate(dev))) {
-		usb_log_error("Failed to enumerate roothub device: %s", str_error(err));
-		goto err_usb_dev;
-	}
-
-	if ((err = ddf_fun_bind(dev->fun))) {
-		usb_log_error("Failed to register roothub: %s.", str_error(err));
-		goto err_enumerated;
-	}
-
-	return EOK;
-
-err_enumerated:
-	bus_device_gone(dev);
-err_usb_dev:
-	hcd_ddf_fun_destroy(dev);
-	return err;
+void hc_reset_toggles(const usb_transfer_batch_t *batch, endpoint_reset_toggle_t reset_cb)
+{
+	assert(reset_cb);
+	assert(batch->ep);
+	assert(batch->ep->device);
+
+	if (batch->error != EOK)
+		return;
+
+	toggle_reset_mode_t mode = get_request_toggle_reset_mode(batch);
+
+	if (mode == RESET_NONE)
+		return;
+
+	if (mode == RESET_ALL) {
+		const device_t *dev = batch->ep->device;
+		for (usb_endpoint_t i = 0; i < 2 * USB_ENDPOINT_MAX; ++i) {
+			if (dev->endpoints[i])
+				reset_cb(dev->endpoints[i]);
+		}
+	} else {
+		reset_cb(batch->ep);
+	}
 }
 
