Index: uspace/drv/bus/usb/usbhub/status.h
===================================================================
--- uspace/drv/bus/usb/usbhub/status.h	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/usbhub/status.h	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -112,4 +112,5 @@
 	if ((status & USB_HUB_PORT_STATUS_HIGH_SPEED) != 0)
 		return USB_SPEED_HIGH;
+	/* TODO: add super speed */
 	return USB_SPEED_FULL;
 }
Index: uspace/drv/bus/usb/xhci/Makefile
===================================================================
--- uspace/drv/bus/usb/xhci/Makefile	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/xhci/Makefile	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -45,13 +45,14 @@
 
 SOURCES = \
+	bus.c \
+	commands.c \
+	debug.c \
+	endpoint.c \
 	hc.c \
-	endpoint.c \
-	debug.c \
-	trb_ring.c \
+	main.c \
+	rh.c \
 	scratchpad.c \
-	commands.c \
 	transfers.c \
-	rh.c \
-	main.c
+	trb_ring.c
 
 TEST_SOURCES = \
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -34,46 +34,37 @@
  */
 
+#include <usb/host/endpoint.h>
+
 #include <errno.h>
 
+#include "bus.h"
 #include "endpoint.h"
 
-int endpoint_init(hcd_t *hcd, endpoint_t *ep)
+int xhci_endpoint_init(xhci_endpoint_t *xhci_ep, xhci_bus_t *xhci_bus)
 {
-	assert(ep);
-	xhci_endpoint_t *xhci_ep = malloc(sizeof(xhci_endpoint_t));
-	if (xhci_ep == NULL)
-		return ENOMEM;
+	assert(xhci_ep);
+	assert(xhci_bus);
+
+	bus_t *bus = &xhci_bus->base;
+	endpoint_t *ep = &xhci_ep->base;
+
+	endpoint_init(ep, bus);
 
 	/* FIXME: Set xhci_ep->slot_id */
 
-	fibril_mutex_lock(&ep->guard);
-	ep->hc_data.data = xhci_ep;
-	/* FIXME: The two handlers below should be implemented. */
-	ep->hc_data.toggle_get = NULL;
-	ep->hc_data.toggle_set = NULL;
-	fibril_mutex_unlock(&ep->guard);
-
-	usb_log_debug("Endpoint %d:%d initialized.", ep->address, ep->endpoint);
+	usb_log_debug("XHCI Endpoint %d:%d initialized.", ep->target.address, ep->target.endpoint);
 
 	return EOK;
 }
 
-void endpoint_fini(hcd_t *hcd, endpoint_t *ep)
+void xhci_endpoint_fini(xhci_endpoint_t *xhci_ep)
 {
-	assert(hcd);
-	assert(ep);
-	xhci_endpoint_t *xhci_ep = endpoint_get(ep);
+	assert(xhci_ep);
+
 	/* FIXME: Tear down TR's? */
-	if (xhci_ep) {
-		free(xhci_ep);
-	}
 
-	fibril_mutex_lock(&ep->guard);
-	ep->hc_data.data = NULL;
-	ep->hc_data.toggle_get = NULL;
-	ep->hc_data.toggle_set = NULL;
-	fibril_mutex_unlock(&ep->guard);
+	endpoint_t *ep = &xhci_ep->base;
 
-	usb_log_debug("Endpoint %d:%d destroyed.", ep->address, ep->endpoint);
+	usb_log_debug("XHCI Endpoint %d:%d destroyed.", ep->target.address, ep->target.endpoint);
 }
 
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -43,4 +43,7 @@
 #include <usb/host/hcd.h>
 
+typedef struct xhci_endpoint xhci_endpoint_t;
+typedef struct xhci_bus xhci_bus_t;
+
 enum {
 	EP_TYPE_INVALID = 0,
@@ -56,14 +59,16 @@
 /** Connector structure linking endpoint context to the endpoint. */
 typedef struct xhci_endpoint {
+	endpoint_t base;	/**< Inheritance. Keep this first. */
+
 	uint32_t slot_id;
 } xhci_endpoint_t;
 
-int endpoint_init(hcd_t *hcd, endpoint_t *ep);
-void endpoint_fini(hcd_t *hcd, endpoint_t *ep);
+int xhci_endpoint_init(xhci_endpoint_t *, xhci_bus_t *);
+void xhci_endpoint_fini(xhci_endpoint_t *);
 
-static inline xhci_endpoint_t * endpoint_get(const endpoint_t *ep)
+static inline xhci_endpoint_t * xhci_endpoint_get(endpoint_t *ep)
 {
 	assert(ep);
-	return ep->hc_data.data;
+	return (xhci_endpoint_t *) ep;
 }
 
Index: uspace/drv/bus/usb/xhci/hc.c
===================================================================
--- uspace/drv/bus/usb/xhci/hc.c	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/xhci/hc.c	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -447,5 +447,5 @@
 
 	/* Check for root hub communication */
-	if (batch->ep->address == xhci_rh_get_address(&hc->rh)) {
+	if (batch->ep->target.address == xhci_rh_get_address(&hc->rh)) {
 		usb_log_debug("XHCI root hub request.\n");
 		return xhci_rh_schedule(&hc->rh, batch);
@@ -453,9 +453,9 @@
 
 	usb_log_debug2("EP(%d:%d) started %s transfer of size %lu.",
-		batch->ep->address, batch->ep->endpoint,
+		batch->ep->target.address, batch->ep->target.endpoint,
 		usb_str_transfer_type(batch->ep->transfer_type),
 		batch->buffer_size);
 
-	if (!batch->ep->address) {
+	if (!batch->ep->target.address) {
 		usb_log_error("Attempted to schedule transfer to address 0.");
 		return EINVAL;
Index: uspace/drv/bus/usb/xhci/hc.h
===================================================================
--- uspace/drv/bus/usb/xhci/hc.h	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/xhci/hc.h	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -43,4 +43,5 @@
 #include "trb_ring.h"
 #include "rh.h"
+#include "bus.h"
 
 typedef struct xhci_virt_device_ctx {
@@ -72,4 +73,7 @@
 	xhci_rh_t rh;
 
+	/* Bus bookkeeping */
+	xhci_bus_t bus;
+
 	/* Cached capabilities */
 	unsigned max_slots;
Index: uspace/drv/bus/usb/xhci/main.c
===================================================================
--- uspace/drv/bus/usb/xhci/main.c	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/xhci/main.c	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -66,6 +66,4 @@
 		.schedule       = hcd_schedule,
 		.irq_hook       = hcd_interrupt,
-		.ep_add_hook    = endpoint_init,
-		.ep_remove_hook = endpoint_fini,
 		.status_hook    = hcd_status,
 	}
@@ -83,8 +81,11 @@
 		goto err;
 
+	if ((err = xhci_bus_init(&hc->bus, hcd)))
+		goto err;
+
 	if ((err = hc_init_memory(hc)))
 		goto err;
 
-	hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops);
+	hcd_set_implementation(hcd, hc, &xhci_ddf_hc_driver.ops, &hc->bus.base);
 
 	return EOK;
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -266,8 +266,5 @@
 	assert(rh);
 	assert(batch);
-	const usb_target_t target = {{
-		.address = batch->ep->address,
-		.endpoint = batch->ep->endpoint,
-	}};
+	const usb_target_t target = batch->ep->target;
 	batch->error = virthub_base_request(&rh->base, target,
 	    usb_transfer_batch_direction(batch), (void*)batch->setup_buffer,
@@ -294,8 +291,5 @@
 	rh->unfinished_interrupt_transfer = NULL;
 	if (batch) {
-		const usb_target_t target = {{
-			.address = batch->ep->address,
-			.endpoint = batch->ep->endpoint,
-		}};
+		const usb_target_t target = batch->ep->target;
 		batch->error = virthub_base_request(&rh->base, target,
 		    usb_transfer_batch_direction(batch),
Index: uspace/drv/bus/usb/xhci/transfers.c
===================================================================
--- uspace/drv/bus/usb/xhci/transfers.c	(revision 7e749112b819fef86c72a9b9f38799d1e29b9476)
+++ uspace/drv/bus/usb/xhci/transfers.c	(revision 41924f3000a0433bb9a3bac4c10f0768464cc2e7)
@@ -36,4 +36,5 @@
 #include <usb/host/utils/malloc32.h>
 #include <usb/debug.h>
+#include "endpoint.h"
 #include "hc.h"
 #include "hw_struct/trb.h"
@@ -141,5 +142,5 @@
 		return EINVAL;
 	}
-	if (batch->ep->endpoint != 0 || batch->ep->transfer_type != USB_TRANSFER_CONTROL) {
+	if (batch->ep->target.endpoint != 0 || batch->ep->transfer_type != USB_TRANSFER_CONTROL) {
 		/* This method only works for control transfers. */
 		usb_log_error("Attempted to schedule control transfer to non 0 endpoint.");
@@ -147,5 +148,7 @@
 	}
 
-	uint8_t slot_id = batch->ep->hc_data.slot_id;
+	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep);
+
+	uint8_t slot_id = xhci_ep->slot_id;
 	xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[0];
 
@@ -230,6 +233,7 @@
 	}
 
-	uint8_t slot_id = batch->ep->hc_data.slot_id;
-	xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[batch->ep->endpoint];
+	xhci_endpoint_t *xhci_ep = xhci_endpoint_get(batch->ep);
+	uint8_t slot_id = xhci_ep->slot_id;
+	xhci_trb_ring_t* ring = hc->dcbaa_virt[slot_id].trs[batch->ep->target.endpoint];
 
 	xhci_transfer_t *transfer = xhci_transfer_alloc(batch);
