Index: uspace/drv/bus/usb/xhci/Makefile
===================================================================
--- uspace/drv/bus/usb/xhci/Makefile	(revision 5ff9e1d9c1d85af952fb4f90f9618bfdf5e8c811)
+++ uspace/drv/bus/usb/xhci/Makefile	(revision d32d51d3e10cd574c12b571c736c1578affbd6b8)
@@ -31,4 +31,5 @@
 LIBS = \
 	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSBVIRT_PREFIX)/libusbvirt.a \
 	$(LIBUSB_PREFIX)/libusb.a \
 	$(LIBDRV_PREFIX)/libdrv.a
@@ -36,5 +37,7 @@
 EXTRA_CFLAGS += \
 	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
 	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBUSBVIRT_PREFIX)/include \
 	-I$(LIBDRV_PREFIX)/include
 
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision 5ff9e1d9c1d85af952fb4f90f9618bfdf5e8c811)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision d32d51d3e10cd574c12b571c736c1578affbd6b8)
@@ -55,4 +55,5 @@
 
 	usb_log_debug("Endpoint %d:%d initialized.", ep->address, ep->endpoint);
+
 	return EOK;
 }
Index: uspace/drv/bus/usb/xhci/hc.c
===================================================================
--- uspace/drv/bus/usb/xhci/hc.c	(revision 5ff9e1d9c1d85af952fb4f90f9618bfdf5e8c811)
+++ uspace/drv/bus/usb/xhci/hc.c	(revision d32d51d3e10cd574c12b571c736c1578affbd6b8)
@@ -220,6 +220,11 @@
 		goto err_event_ring;
 
-	return EOK;
-
+	if ((err = xhci_rh_init(&hc->rh)))
+		goto err_rh;
+
+	return EOK;
+
+err_rh:
+	xhci_rh_fini(&hc->rh);
 err_event_ring:
 	xhci_event_ring_fini(&hc->event_ring);
@@ -362,4 +367,11 @@
 	assert(batch);
 
+	/* Check for root hub communication */
+	/* FIXME: Zero is a very crude workaround. Detect RH better. */
+	if (batch->ep->address == 0) {
+		usb_log_debug("XHCI root hub request.\n");
+		return xhci_rh_schedule(&hc->rh, batch);
+	}
+
 	usb_log_debug2("EP(%d:%d) started %s transfer of size %lu.",
 		batch->ep->address, batch->ep->endpoint,
@@ -386,5 +398,5 @@
 	}
 
-	return ENAK;
+	return EOK;
 }
 
@@ -515,4 +527,5 @@
 	hc_dcbaa_fini(hc);
 	xhci_fini_commands(hc);
+	xhci_rh_fini(&hc->rh);
 	pio_disable(hc->base, RNGSZ(hc->mmio_range));
 	usb_log_info("HC(%p): Finalized.", hc);
Index: uspace/drv/bus/usb/xhci/hc.h
===================================================================
--- uspace/drv/bus/usb/xhci/hc.h	(revision 5ff9e1d9c1d85af952fb4f90f9618bfdf5e8c811)
+++ uspace/drv/bus/usb/xhci/hc.h	(revision d32d51d3e10cd574c12b571c736c1578affbd6b8)
@@ -42,4 +42,5 @@
 #include "scratchpad.h"
 #include "trb_ring.h"
+#include "rh.h"
 
 typedef struct xhci_virt_device_ctx {
@@ -75,4 +76,7 @@
 	xhci_scratchpad_t *scratchpad;
 
+  /* Root hub emulation */
+	xhci_rh_t rh;
+
 	/* Cached capabilities */
 	xhci_port_speed_t speeds [16];
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision 5ff9e1d9c1d85af952fb4f90f9618bfdf5e8c811)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision d32d51d3e10cd574c12b571c736c1578affbd6b8)
@@ -44,4 +44,10 @@
 #include "rh.h"
 
+int xhci_rh_init(xhci_rh_t *rh)
+{
+	/* TODO: Implement me! */
+	return EOK;
+}
+
 // TODO: Check device deallocation, we free device_ctx in hc.c, not
 //       sure about the other structs.
@@ -221,4 +227,16 @@
 }
 
+int xhci_rh_schedule(xhci_rh_t *rh, usb_transfer_batch_t *batch)
+{
+	/* TODO: Implement me! */
+	return EOK;
+}
+
+int xhci_rh_fini(xhci_rh_t *rh)
+{
+	/* TODO: Implement me! */
+	return EOK;
+}
+
 
 /**
Index: uspace/drv/bus/usb/xhci/rh.h
===================================================================
--- uspace/drv/bus/usb/xhci/rh.h	(revision 5ff9e1d9c1d85af952fb4f90f9618bfdf5e8c811)
+++ uspace/drv/bus/usb/xhci/rh.h	(revision d32d51d3e10cd574c12b571c736c1578affbd6b8)
@@ -37,7 +37,19 @@
 #define XHCI_RH_H
 
+#include <usb/host/usb_transfer_batch.h>
+#include <usbvirt/virthub_base.h>
+
+/* XHCI root hub instance */
+typedef struct {
+	/** Virtual hub instance */
+	virthub_base_t base;
+} xhci_rh_t;
+
+int xhci_rh_init(xhci_rh_t *);
+int xhci_rh_fini(xhci_rh_t *);
 int xhci_handle_port_status_change_event(xhci_hc_t *, xhci_trb_t *);
 int xhci_get_hub_port(xhci_trb_t *);
 int xhci_reset_hub_port(xhci_hc_t *, uint8_t);
+int xhci_rh_schedule(xhci_rh_t *, usb_transfer_batch_t *);
 
 #endif
