Index: uspace/drv/bus/usb/ehci/hc.c
===================================================================
--- uspace/drv/bus/usb/ehci/hc.c	(revision e76c0ea8f951c2e63efa8e948fc849e59dec918b)
+++ uspace/drv/bus/usb/ehci/hc.c	(revision 306a36dae0d419ae43d028501b23fce889c83a66)
@@ -238,6 +238,6 @@
 	assert(ep);
 	ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
-	usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)\n", instance,
-	    ep->device->address, ep->endpoint,
+	usb_log_debug("HC(%p) dequeue EP(?:%d:%s:%s)\n", instance,
+	    ep->endpoint,
 	    usb_str_transfer_type_short(ep->transfer_type),
 	    usb_str_direction(ep->direction));
Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision e76c0ea8f951c2e63efa8e948fc849e59dec918b)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 306a36dae0d419ae43d028501b23fce889c83a66)
@@ -50,7 +50,5 @@
 
 
-/* FIXME Are these really static? Older HCs fetch it from descriptor. */
-/* FIXME Add USB3 options, if applicable. */
-static const usb_endpoint_desc_t ep0_desc = {
+static const usb_endpoint_desc_t ep0_initial_desc = {
 	.endpoint_no = 0,
 	.direction = USB_DIRECTION_BOTH,
@@ -97,5 +95,5 @@
 	xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base);
 
-	if ((err = prepare_endpoint(ep0, &ep0_desc)))
+	if ((err = prepare_endpoint(ep0, &ep0_initial_desc)))
 		goto err_ep;
 
@@ -124,4 +122,29 @@
 }
 
+static int setup_ep0_packet_size(xhci_hc_t *hc, xhci_device_t *dev)
+{
+	int err;
+
+	uint16_t max_packet_size;
+	if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, hc->hcd, &dev->base)))
+		return err;
+
+	xhci_endpoint_t *ep0 = dev->endpoints[0];
+	assert(ep0);
+
+	if (ep0->base.max_packet_size == max_packet_size)
+		return EOK;
+
+	ep0->base.max_packet_size = max_packet_size;
+
+	xhci_ep_ctx_t ep_ctx;
+	xhci_setup_endpoint_context(ep0, &ep_ctx);
+
+	if ((err = hc_update_endpoint(hc, dev->slot_id, 0, &ep_ctx)))
+		return err;
+
+	return EOK;
+}
+
 int xhci_bus_enumerate_device(xhci_bus_t *bus, xhci_hc_t *hc, device_t *dev)
 {
@@ -160,6 +183,8 @@
 	}
 
-	// TODO: Fetch descriptor of EP0 and reconfigure it accordingly
-	assert(xhci_dev->endpoints[0]);
+	if ((err = setup_ep0_packet_size(hc, xhci_dev))) {
+		usb_log_error("Failed to setup control endpoint of the new device: %s", str_error(err));
+		goto err_address;
+	}
 
 	assert(bus->devices_by_slot[xhci_dev->slot_id] == NULL);
Index: uspace/drv/bus/usb/xhci/hc.c
===================================================================
--- uspace/drv/bus/usb/xhci/hc.c	(revision e76c0ea8f951c2e63efa8e948fc849e59dec918b)
+++ uspace/drv/bus/usb/xhci/hc.c	(revision 306a36dae0d419ae43d028501b23fce889c83a66)
@@ -651,6 +651,4 @@
 }
 
-// TODO: This currently assumes the device is attached to rh directly
-//	-> calculate route string
 int hc_address_device(xhci_hc_t *hc, xhci_device_t *dev, xhci_endpoint_t *ep0)
 {
@@ -767,4 +765,20 @@
 }
 
+int hc_update_endpoint(xhci_hc_t *hc, uint32_t slot_id, uint8_t ep_idx, xhci_ep_ctx_t *ep_ctx)
+{
+	dma_buffer_t ictx_dma_buf;
+	const int err = dma_buffer_alloc(&ictx_dma_buf, sizeof(xhci_input_ctx_t));
+	if (err)
+		return err;
+
+	xhci_input_ctx_t *ictx = ictx_dma_buf.virt;
+	memset(ictx, 0, sizeof(xhci_input_ctx_t));
+
+	XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1);
+	memcpy(&ictx->endpoint_ctx[ep_idx], ep_ctx, sizeof(xhci_ep_ctx_t));
+
+	return xhci_cmd_sync_inline(hc, EVALUATE_CONTEXT, .slot_id = slot_id, .input_ctx = ictx_dma_buf);
+}
+
 /**
  * @}
Index: uspace/drv/bus/usb/xhci/hc.h
===================================================================
--- uspace/drv/bus/usb/xhci/hc.h	(revision e76c0ea8f951c2e63efa8e948fc849e59dec918b)
+++ uspace/drv/bus/usb/xhci/hc.h	(revision 306a36dae0d419ae43d028501b23fce889c83a66)
@@ -110,4 +110,5 @@
 int hc_add_endpoint(xhci_hc_t *, uint32_t, uint8_t, xhci_ep_ctx_t *);
 int hc_drop_endpoint(xhci_hc_t *, uint32_t, uint8_t);
+int hc_update_endpoint(xhci_hc_t *, uint32_t, uint8_t, xhci_ep_ctx_t *);
 
 #endif
Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision e76c0ea8f951c2e63efa8e948fc849e59dec918b)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision 306a36dae0d419ae43d028501b23fce889c83a66)
@@ -102,4 +102,6 @@
 }
 
+extern int hcd_get_ep0_max_packet_size(uint16_t *, hcd_t *, device_t *);
+
 extern int hcd_send_batch(hcd_t *, device_t *, usb_target_t,
     usb_direction_t direction, char *, size_t, uint64_t,
Index: uspace/lib/usbhost/src/hcd.c
===================================================================
--- uspace/lib/usbhost/src/hcd.c	(revision e76c0ea8f951c2e63efa8e948fc849e59dec918b)
+++ uspace/lib/usbhost/src/hcd.c	(revision 306a36dae0d419ae43d028501b23fce889c83a66)
@@ -35,4 +35,5 @@
 
 #include <usb/debug.h>
+#include <usb/descriptor.h>
 #include <usb/request.h>
 
@@ -40,4 +41,5 @@
 #include <async.h>
 #include <errno.h>
+#include <macros.h>
 #include <usb_iface.h>
 #include <str_error.h>
@@ -59,4 +61,50 @@
 	hcd_set_implementation(hcd, NULL, NULL, NULL);
 }
+
+/** Get max packet size for the control endpoint 0.
+ *
+ * For LS, HS, and SS devices this value is fixed. For FS devices we must fetch
+ * the first 8B of the device descriptor to determine it.
+ *
+ * @return Combined value of max_packet_size and scheduling oppertunities,
+ *	see usb_standard_device_descriptor_t.
+ */
+int hcd_get_ep0_max_packet_size(uint16_t *mps, hcd_t *hcd, device_t *dev)
+{
+	static const uint16_t mps_fixed [] = {
+		[USB_SPEED_LOW] = 8,
+		[USB_SPEED_HIGH] = 64,
+		[USB_SPEED_SUPER] = 512,
+	};
+
+	if (dev->speed < ARRAY_SIZE(mps_fixed) && mps_fixed[dev->speed] != 0) {
+		*mps = mps_fixed[dev->speed];
+		return EOK;
+	}
+
+	const usb_target_t control_ep = {{
+		.address = dev->address,
+		.endpoint = 0,
+	}};
+
+	usb_standard_device_descriptor_t desc = { 0 };
+	const usb_device_request_setup_packet_t get_device_desc_8 =
+	    GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
+
+	usb_log_debug("Requesting first 8B of device descriptor.");
+	ssize_t got = hcd_send_batch_sync(hcd, dev, control_ep, USB_DIRECTION_IN,
+	    (char *) &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
+	    "read first 8 bytes of dev descriptor");
+
+	if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
+		const int err = got < 0 ? got : EOVERFLOW;
+		usb_log_error("Failed to get 8B of dev descr: %s.", str_error(err));
+		return err;
+	}
+
+	*mps = uint16_usb2host(desc.max_packet_size);
+	return EOK;
+}
+
 
 /** Prepare generic usb_transfer_batch and schedule it.
Index: uspace/lib/usbhost/src/usb2_bus.c
===================================================================
--- uspace/lib/usbhost/src/usb2_bus.c	(revision e76c0ea8f951c2e63efa8e948fc849e59dec918b)
+++ uspace/lib/usbhost/src/usb2_bus.c	(revision 306a36dae0d419ae43d028501b23fce889c83a66)
@@ -132,21 +132,7 @@
 	}
 
-	/* Get max packet size for default pipe */
-	usb_standard_device_descriptor_t desc = { 0 };
-	const usb_device_request_setup_packet_t get_device_desc_8 =
-	    GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
-
-	usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
-	    address);
-	ssize_t got = hcd_send_batch_sync(hcd, dev, usb2_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");
-
-	if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
-		err = got < 0 ? got : EOVERFLOW;
-		usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
-		    address, str_error(err));
-		goto err_default_control_ep;
-	}
+	uint16_t max_packet_size;
+	if ((err = hcd_get_ep0_max_packet_size(&max_packet_size, hcd, dev)))
+		goto err_address;
 
 	/* Set new address */
@@ -158,5 +144,5 @@
 	if (err != 0) {
 		usb_log_error("Device(%d): Failed to set new address: %s.",
-		    address, str_error(got));
+		    address, str_error(err));
 		goto err_default_control_ep;
 	}
@@ -175,6 +161,6 @@
 		.transfer_type = USB_TRANSFER_CONTROL,
 		.direction = USB_DIRECTION_BOTH,
-		.max_packet_size = ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
-		.packets = ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
+		.max_packet_size = max_packet_size,
+		.packets = 1,
 	};
 
