Index: uspace/drv/bus/usb/ehci/ehci_bus.c
===================================================================
--- uspace/drv/bus/usb/ehci/ehci_bus.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/drv/bus/usb/ehci/ehci_bus.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -114,10 +114,12 @@
 
 
-static int ehci_register_ep(bus_t *bus_base, endpoint_t *ep)
+static int ehci_register_ep(bus_t *bus_base, endpoint_t *ep, const usb_endpoint_desc_t *desc)
 {
 	ehci_bus_t *bus = (ehci_bus_t *) bus_base;
 	ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep);
 
-	const int err = bus->parent_ops.register_endpoint(bus_base, ep);
+	// TODO utilize desc->usb2
+
+	const int err = bus->parent_ops.register_endpoint(bus_base, ep, desc);
 	if (err)
 		return err;
Index: uspace/drv/bus/usb/ohci/ohci_bus.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_bus.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/drv/bus/usb/ohci/ohci_bus.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -115,10 +115,10 @@
 
 
-static int ohci_register_ep(bus_t *bus_base, endpoint_t *ep)
+static int ohci_register_ep(bus_t *bus_base, endpoint_t *ep, const usb_endpoint_desc_t *desc)
 {
 	ohci_bus_t *bus = (ohci_bus_t *) bus_base;
 	ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
 
-	const int err = bus->parent_ops.register_endpoint(bus_base, ep);
+	const int err = bus->parent_ops.register_endpoint(bus_base, ep, desc);
 	if (err)
 		return err;
Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -165,13 +165,30 @@
 }
 
-static int register_endpoint(bus_t *bus_base, endpoint_t *ep)
+static int register_endpoint(bus_t *bus_base, endpoint_t *ep, const usb_endpoint_desc_t *desc)
 {
 	xhci_bus_t *bus = bus_to_xhci_bus(bus_base);
 	assert(bus);
 
-	usb_log_info("Endpoint(%d:%d) registered to XHCI bus.", ep->target.address, ep->target.endpoint);
+	assert(ep->device);
+
+	/* Extract USB2-related information from endpoint_desc */
+	ep->target = (usb_target_t) {{
+		.address = ep->device->address,
+		.endpoint = desc->endpoint_no,
+	}};
+	ep->direction = desc->direction;
+	ep->transfer_type = desc->transfer_type;
+	ep->max_packet_size = desc->max_packet_size;
+	ep->packets = desc->packets;
 
 	xhci_device_t *xhci_dev = xhci_device_get(ep->device);
 	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(ep);
+
+	xhci_ep->max_streams = desc->usb3.max_streams;
+	xhci_ep->max_burst = desc->usb3.max_burst;
+	// TODO add this property to usb_endpoint_desc_t and fetch it from ss companion desc
+	xhci_ep->mult = 0;
+
+	usb_log_info("Endpoint(%d:%d) registered to XHCI bus.", ep->target.address, ep->target.endpoint);
 	return xhci_device_add_endpoint(xhci_dev, xhci_ep);
 }
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -275,4 +275,6 @@
 	assert(&dev->base == ep->base.device);
 	assert(dev->base.address == ep->base.target.address);
+
+	// TODO Do not fail hard on runtime conditions
 	assert(!dev->endpoints[ep_num]);
 
@@ -285,9 +287,4 @@
 		return EOK;
 	}
-
-	// FIXME: Set these from usb_superspeed_endpoint_companion_descriptor_t:
-	ep->max_streams = 0;
-	ep->max_burst = 0;
-	ep->mult = 0;
 
 	/* Set up TRB ring / PSA. */
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -90,4 +90,14 @@
 }
 
+/* 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 = {
+	.endpoint_no = 0,
+	.direction = USB_DIRECTION_BOTH,
+	.transfer_type = USB_TRANSFER_CONTROL,
+	.max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
+	.packets = 1,
+};
+
 // TODO: This currently assumes the device is attached to rh directly.
 //       Also, we should consider moving a lot of functionailty to xhci bus
@@ -112,8 +122,4 @@
 
 	xhci_endpoint_t *ep0 = xhci_endpoint_get(ep0_base);
-	/* FIXME: Sync this with xhci_device_add_endpoint. */
-	ep0->max_streams = 0;
-	ep0->max_burst = 0;
-	ep0->mult = 0;
 
 	if ((err = xhci_endpoint_alloc_transfer_ds(ep0)))
@@ -144,15 +150,7 @@
 	fibril_mutex_unlock(&dev->guard);
 
-	// XXX: Going around bus, duplicating code
 	ep0_base->device = dev;
-	ep0_base->target.address = dev->address;
-	ep0_base->target.endpoint = 0;
-	ep0_base->direction = USB_DIRECTION_BOTH;
-	ep0_base->transfer_type = USB_TRANSFER_CONTROL;
-	ep0_base->max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE;
-	ep0_base->packets = 1;
-	ep0_base->bandwidth = CTRL_PIPE_MIN_PACKET_SIZE;
-
-	bus_register_endpoint(&rh->hc->bus.base, ep0_base);
+
+	bus_register_endpoint(&rh->hc->bus.base, ep0_base, &ep0_desc);
 
 	if (!rh->devices[dev->port - 1]) {
Index: uspace/lib/usbhost/include/usb/host/bus.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/bus.h	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/lib/usbhost/include/usb/host/bus.h	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -83,5 +83,5 @@
 
 	endpoint_t *(*create_endpoint)(bus_t *);
-	int (*register_endpoint)(bus_t *, endpoint_t *);
+	int (*register_endpoint)(bus_t *, endpoint_t *, const usb_endpoint_desc_t *);
 	int (*unregister_endpoint)(bus_t *, endpoint_t *);
 	endpoint_t *(*find_endpoint)(bus_t *, device_t*, usb_target_t, usb_direction_t);
@@ -117,7 +117,5 @@
 int device_init(device_t *);
 
-extern int bus_add_ep(bus_t *bus, device_t *device, usb_endpoint_t endpoint,
-    usb_direction_t dir, usb_transfer_type_t type, size_t max_packet_size,
-    unsigned packets, size_t size);
+extern int bus_add_ep(bus_t *, device_t *, const usb_endpoint_desc_t *);
 extern int bus_remove_ep(bus_t *, device_t *, usb_target_t, usb_direction_t);
 
@@ -128,5 +126,5 @@
 
 endpoint_t *bus_create_endpoint(bus_t *);
-int bus_register_endpoint(bus_t *, endpoint_t *);
+int bus_register_endpoint(bus_t *, endpoint_t *, const usb_endpoint_desc_t *);
 int bus_unregister_endpoint(bus_t *, endpoint_t *);
 endpoint_t *bus_find_endpoint(bus_t *, device_t *, usb_target_t, usb_direction_t);
Index: uspace/lib/usbhost/src/bus.c
===================================================================
--- uspace/lib/usbhost/src/bus.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/lib/usbhost/src/bus.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -66,7 +66,5 @@
 }
 
-int bus_add_ep(bus_t *bus, device_t *device, usb_endpoint_t endpoint,
-    usb_direction_t dir, usb_transfer_type_t type, size_t max_packet_size,
-    unsigned packets, size_t size)
+int bus_add_ep(bus_t *bus, device_t *device, const usb_endpoint_desc_t *desc)
 {
 	assert(bus);
@@ -78,18 +76,6 @@
 		return ENOMEM;
 
-	ep->target = (usb_target_t) {
-		.address = device->address,
-		.endpoint = endpoint,
-	};
-
 	ep->device = device;
-	ep->direction = dir;
-	ep->transfer_type = type;
-	ep->max_packet_size = max_packet_size;
-	ep->packets = packets;
-
-	ep->bandwidth = bus_count_bw(ep, size);
-
-	const int err = bus_register_endpoint(bus, ep);
+	const int err = bus_register_endpoint(bus, ep, desc);
 
 	/* drop Temporary reference */
@@ -165,5 +151,5 @@
 }
 
-int bus_register_endpoint(bus_t *bus, endpoint_t *ep)
+int bus_register_endpoint(bus_t *bus, endpoint_t *ep, const usb_endpoint_desc_t *desc)
 {
 	assert(bus);
@@ -174,5 +160,5 @@
 
 	fibril_mutex_lock(&bus->guard);
-	const int r = bus->ops.register_endpoint(bus, ep);
+	const int r = bus->ops.register_endpoint(bus, ep, desc);
 	fibril_mutex_unlock(&bus->guard);
 
Index: uspace/lib/usbhost/src/ddf_helpers.c
===================================================================
--- uspace/lib/usbhost/src/ddf_helpers.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/lib/usbhost/src/ddf_helpers.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -98,6 +98,4 @@
 	assert(dev);
 
-	const size_t size = endpoint_desc->max_packet_size;
-
 	usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n",
 		dev->address, endpoint_desc->endpoint_no,
@@ -106,11 +104,5 @@
 		endpoint_desc->max_packet_size, endpoint_desc->usb2.polling_interval);
 
-	// FIXME: we now have max_streams and max_burst in endpoint_desc->usb3 struct
-	// Hand it down to XHCI, refactor, whatever
-
-	return bus_add_ep(hcd->bus, dev, endpoint_desc->endpoint_no,
-		endpoint_desc->direction, endpoint_desc->transfer_type,
-		endpoint_desc->max_packet_size, endpoint_desc->packets,
-		size);
+	return bus_add_ep(hcd->bus, dev, endpoint_desc);
 }
 
Index: uspace/lib/usbhost/src/hcd.c
===================================================================
--- uspace/lib/usbhost/src/hcd.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/lib/usbhost/src/hcd.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -87,4 +87,9 @@
 	assert(device->address == target.address);
 
+	if (!hcd->ops.schedule) {
+		usb_log_error("HCD does not implement scheduler.\n");
+		return ENOTSUP;
+	}
+
 	endpoint_t *ep = bus_find_endpoint(hcd->bus, device, target, direction);
 	if (ep == NULL) {
@@ -93,4 +98,6 @@
 		return ENOENT;
 	}
+
+	// TODO cut here aka provide helper to call with instance of endpoint_t in hand
 
 	usb_log_debug2("%s %d:%d %zu(%zu).\n",
@@ -104,8 +111,4 @@
 		    ep->target.address, ep->target.endpoint, name, bw, ep->bandwidth);
 		return ENOSPC;
-	}
-	if (!hcd->ops.schedule) {
-		usb_log_error("HCD does not implement scheduler.\n");
-		return ENOTSUP;
 	}
 
Index: uspace/lib/usbhost/src/usb2_bus.c
===================================================================
--- uspace/lib/usbhost/src/usb2_bus.c	(revision 894f58c6a9276891cb9de8f06bba34477d4b7f50)
+++ uspace/lib/usbhost/src/usb2_bus.c	(revision 56db65dc41b80ff74d067c9103026ffe34cc8e46)
@@ -91,12 +91,21 @@
 }
 
+static const usb_endpoint_desc_t usb2_default_control_ep = {
+	.endpoint_no = 0,
+	.transfer_type = USB_TRANSFER_CONTROL,
+	.direction = USB_DIRECTION_BOTH,
+	.max_packet_size = CTRL_PIPE_MIN_PACKET_SIZE,
+	.packets = 1,
+};
+
+
+static const usb_target_t usb2_default_target = {{
+	.address = USB_ADDRESS_DEFAULT,
+	.endpoint = 0,
+}};
+
 static int usb2_bus_address_device(bus_t *bus, hcd_t *hcd, device_t *dev)
 {
 	int err;
-
-	static const usb_target_t default_target = {{
-		.address = USB_ADDRESS_DEFAULT,
-		.endpoint = 0,
-	}};
 
 	/** Reserve address early, we want pretty log messages */
@@ -111,6 +120,5 @@
 	/* Add default pipe on default address */
 	usb_log_debug("Device(%d): Adding default target (0:0)", address);
-	err = bus_add_ep(bus, dev, 0, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
-	    CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1);
+	err = bus_add_ep(bus, dev, &usb2_default_control_ep);
 	if (err != EOK) {
 		usb_log_error("Device(%d): Failed to add default target: %s.",
@@ -126,5 +134,5 @@
 	usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
 	    address);
-	ssize_t got = hcd_send_batch_sync(hcd, dev, default_target, USB_DIRECTION_IN,
+	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");
@@ -134,5 +142,5 @@
 		usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
 		    address, str_error(err));
-		goto err_default_target;
+		goto err_default_control_ep;
 	}
 
@@ -141,31 +149,36 @@
 
 	usb_log_debug("Device(%d): Setting USB address.", address);
-	err = hcd_send_batch_sync(hcd, dev, default_target, USB_DIRECTION_OUT,
+	err = hcd_send_batch_sync(hcd, dev, usb2_default_target, USB_DIRECTION_OUT,
 	    NULL, 0, *(uint64_t *)&set_address, "set address");
 	if (err != 0) {
 		usb_log_error("Device(%d): Failed to set new address: %s.",
 		    address, str_error(got));
-		goto err_default_target;
+		goto err_default_control_ep;
 	}
 
 	dev->address = address;
+
+	const usb_endpoint_desc_t control_ep = {
+		.endpoint_no = 0,
+		.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)),
+	};
 
 	/* Register EP on the new address */
 	usb_log_debug("Device(%d): Registering control EP.", address);
-	err = bus_add_ep(bus, dev, 0, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
-	    ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
-	    ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
-	    ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)));
+	err = bus_add_ep(bus, dev, &control_ep);
 	if (err != EOK) {
 		usb_log_error("Device(%d): Failed to register EP0: %s",
 		    address, str_error(err));
-		goto err_default_target;
-	}
-
-	bus_remove_ep(bus, dev, default_target, USB_DIRECTION_BOTH);
-	return EOK;
-
-err_default_target:
-	bus_remove_ep(bus, dev, default_target, USB_DIRECTION_BOTH);
+		goto err_default_control_ep;
+	}
+
+	bus_remove_ep(bus, dev, usb2_default_target, USB_DIRECTION_BOTH);
+	return EOK;
+
+err_default_control_ep:
+	bus_remove_ep(bus, dev, usb2_default_target, USB_DIRECTION_BOTH);
 err_address:
 	bus_release_address(bus, address);
@@ -278,17 +291,22 @@
  * @param endpoint USB endpoint number.
  */
-static int usb2_bus_register_ep(bus_t *bus_base, endpoint_t *ep)
+static int usb2_bus_register_ep(bus_t *bus_base, endpoint_t *ep, const usb_endpoint_desc_t *desc)
 {
 	usb2_bus_t *bus = bus_to_usb2_bus(bus_base);
 	assert(ep);
 
-	usb_address_t address = ep->target.address;
-
-	if (!usb_address_is_valid(address))
-		return EINVAL;
-
-	/* Check for speed and address */
-	if (!bus->devices[address].occupied)
-		return ENOENT;
+	assert(ep->device);
+
+	/* Extract USB2-related information from endpoint_desc */
+	ep->target = (usb_target_t) {{
+		.address = ep->device->address,
+		.endpoint = desc->endpoint_no,
+	}};
+	ep->direction = desc->direction;
+	ep->transfer_type = desc->transfer_type;
+	ep->max_packet_size = desc->max_packet_size;
+	ep->packets = desc->packets;
+
+	ep->bandwidth = bus_base->ops.count_bw(ep, desc->max_packet_size);
 
 	/* Check for existence */
@@ -300,5 +318,5 @@
 		return ENOSPC;
 
-	list_append(&ep->link, get_list(bus, ep->target.address));
+	list_append(&ep->link, get_list(bus, ep->device->address));
 	bus->free_bw -= ep->bandwidth;
 
