Index: uspace/drv/bus/usb/xhci/commands.c
===================================================================
--- uspace/drv/bus/usb/xhci/commands.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/usb/xhci/commands.c	(revision 60af4cdb1acd8703dcd25885a99082aecd43036f)
@@ -50,4 +50,5 @@
 #define TRB_SET_SUSP(trb, susp) (trb).control |= host2xhci(32, ((susp) & 0x1) << 23)
 #define TRB_SET_SLOT(trb, slot) (trb).control |= host2xhci(32, (slot) << 24)
+#define TRB_SET_DEV_SPEED(trb, speed)	(trb).control |= host2xhci(32, (speed & 0xF) << 16)
 
 /**
@@ -418,4 +419,22 @@
 }
 
+int xhci_get_port_bandwidth_command(xhci_hc_t *hc, xhci_cmd_t *cmd,
+	xhci_port_bandwidth_ctx_t *ctx, uint8_t device_speed)
+{
+	assert(hc);
+	assert(cmd);
+
+	xhci_trb_clean(&cmd->trb);
+
+	uint64_t phys_addr = (uint64_t) addr_to_phys(ctx);
+	TRB_SET_ICTX(cmd->trb, phys_addr);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_GET_PORT_BANDWIDTH_CMD);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+	TRB_SET_DEV_SPEED(cmd->trb, device_speed);
+
+	return enqueue_command(hc, cmd, 0, 0);
+}
+
 int xhci_handle_command_completion(xhci_hc_t *hc, xhci_trb_t *trb)
 {
Index: uspace/drv/bus/usb/xhci/commands.h
===================================================================
--- uspace/drv/bus/usb/xhci/commands.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/usb/xhci/commands.h	(revision 60af4cdb1acd8703dcd25885a99082aecd43036f)
@@ -44,4 +44,5 @@
 typedef struct xhci_hc xhci_hc_t;
 typedef struct xhci_input_ctx xhci_input_ctx_t;
+typedef struct xhci_port_bandwidth_ctx xhci_port_bandwidth_ctx_t;
 
 typedef struct xhci_command {
@@ -87,4 +88,5 @@
 // TODO: Negotiate bandwidth (optional normative, section 4.6.13).
 // TODO: Set latency tolerance value (optional normative, section 4.6.14).
+int xhci_get_port_bandwidth_command(xhci_hc_t *, xhci_cmd_t *, xhci_port_bandwidth_ctx_t *, uint8_t);
 // TODO: Get port bandwidth (mandatory, but needs root hub implementation, section 4.6.15).
 // TODO: Force header (mandatory, but needs root hub implementation, section 4.6.16).
Index: uspace/drv/bus/usb/xhci/hw_struct/context.h
===================================================================
--- uspace/drv/bus/usb/xhci/hw_struct/context.h	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/usb/xhci/hw_struct/context.h	(revision 60af4cdb1acd8703dcd25885a99082aecd43036f)
@@ -192,3 +192,12 @@
 } __attribute__((packed)) xhci_input_ctx_t;
 
+/**
+ * Port bandwidth context: section 6.2.6
+ * The number of ports depends on the amount of ports available to the hub.
+ */
+typedef struct xhci_port_bandwidth_ctx {
+	uint8_t reserved;
+	uint8_t ports [];
+} __attribute__((packed)) xhci_port_bandwidth_ctx_t;
+
 #endif
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision 95c675b4aa3fea7b424b73892a90b052c673cfd3)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision 60af4cdb1acd8703dcd25885a99082aecd43036f)
@@ -382,4 +382,29 @@
 }
 
+static inline int get_hub_available_bandwidth(xhci_device_t* dev, uint8_t speed, xhci_port_bandwidth_ctx_t *ctx) {
+	// TODO: find a correct place for this function + API
+	// We need speed, because a root hub device has both USB 2 and USB 3 speeds
+	// and the command can query only one of them
+	// ctx is an out parameter as of now
+	assert(dev);
+
+	ctx = malloc(sizeof(xhci_port_bandwidth_ctx_t));
+	if(!ctx)
+		return ENOMEM;
+
+	xhci_cmd_t cmd;
+	xhci_cmd_init(&cmd);
+
+	xhci_get_port_bandwidth_command(dev->hc, &cmd, ctx, speed);
+
+	int err = xhci_cmd_wait(&cmd, 100000);
+	if(err != EOK) {
+		free(ctx);
+		ctx = NULL;
+	}
+
+	return EOK;
+}
+
 const xhci_port_speed_t *xhci_rh_get_port_speed(xhci_rh_t *rh, uint8_t port)
 {
