Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision bdd8842c8d5229ebdbb16f829986f5abb8cafae5)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 17c5e62d0dbb1b04123131491f4743240d75deb7)
@@ -36,4 +36,5 @@
 #include <usb/host/endpoint.h>
 #include <usb/host/hcd.h>
+#include <usb/descriptor.h>
 #include <usb/debug.h>
 
@@ -368,5 +369,8 @@
 static endpoint_t *endpoint_create(device_t *dev, const usb_endpoint_descriptors_t *desc)
 {
-	xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t));
+	const usb_transfer_type_t type = USB_ED_GET_TRANSFER_TYPE(desc->endpoint);
+
+	xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t)
+		+ (type == USB_TRANSFER_ISOCHRONOUS) * sizeof(*ep->isoch));
 	if (!ep)
 		return NULL;
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision bdd8842c8d5229ebdbb16f829986f5abb8cafae5)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision 17c5e62d0dbb1b04123131491f4743240d75deb7)
@@ -89,5 +89,5 @@
 
 	if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
-		xhci_ep->isoch_max_size = desc->companion.bytes_per_interval
+		xhci_ep->isoch->max_size = desc->companion.bytes_per_interval
 			? desc->companion.bytes_per_interval
 			: ep->max_transfer_size;
@@ -95,10 +95,10 @@
 
 		/* Allocate and setup isochronous-specific structures. */
-		xhci_ep->isoch_enqueue = 0;
-		xhci_ep->isoch_dequeue = 0;
-		xhci_ep->isoch_started = false;
-
-		fibril_mutex_initialize(&xhci_ep->isoch_guard);
-		fibril_condvar_initialize(&xhci_ep->isoch_avail);
+		xhci_ep->isoch->enqueue = 0;
+		xhci_ep->isoch->dequeue = 0;
+		xhci_ep->isoch->started = false;
+
+		fibril_mutex_initialize(&xhci_ep->isoch->guard);
+		fibril_condvar_initialize(&xhci_ep->isoch->avail);
 	}
 
@@ -266,6 +266,6 @@
 	int err = EOK;
 	while (i < XHCI_ISOCH_BUFFER_COUNT) {
-		xhci_isoch_transfer_t *transfer = &xhci_ep->isoch_transfers[i];
-		if (dma_buffer_alloc(&transfer->data, xhci_ep->isoch_max_size)) {
+		xhci_isoch_transfer_t *transfer = &xhci_ep->isoch->transfers[i];
+		if (dma_buffer_alloc(&transfer->data, xhci_ep->isoch->max_size)) {
 			err = ENOMEM;
 			break;
@@ -278,5 +278,5 @@
 		--i;
 		while(i >= 0) {
-			dma_buffer_free(&xhci_ep->isoch_transfers[i].data);
+			dma_buffer_free(&xhci_ep->isoch->transfers[i].data);
 			--i;
 		}
@@ -342,5 +342,5 @@
 	if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) {
 		for (size_t i = 0; i < XHCI_ISOCH_BUFFER_COUNT; ++i) {
-			dma_buffer_free(&xhci_ep->isoch_transfers[i].data);
+			dma_buffer_free(&xhci_ep->isoch->transfers[i].data);
 		}
 	}
@@ -417,6 +417,6 @@
 	XHCI_EP_INTERVAL_SET(*ctx, fnzb32(ep->interval) % 32 - 1);
 
-	XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(*ctx, ep->isoch_max_size & 0xFFFF);
-	XHCI_EP_MAX_ESIT_PAYLOAD_HI_SET(*ctx, (ep->isoch_max_size >> 16) & 0xFF);
+	XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(*ctx, ep->isoch->max_size & 0xFFFF);
+	XHCI_EP_MAX_ESIT_PAYLOAD_HI_SET(*ctx, (ep->isoch->max_size >> 16) & 0xFF);
 }
 
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision bdd8842c8d5229ebdbb16f829986f5abb8cafae5)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision 17c5e62d0dbb1b04123131491f4743240d75deb7)
@@ -93,23 +93,25 @@
 	uint32_t interval;
 
-	/** The maximum size of an isochronous transfer and therefore the size of buffers */
-	size_t isoch_max_size;
+	/** This field is a valid pointer for (and only for) isochronous transfers. */
+	struct {
+		/** The maximum size of an isochronous transfer and therefore the size of buffers */
+		size_t max_size;
 
-	/** Isochronous scheduled transfers with respective buffers */
-	#define XHCI_ISOCH_BUFFER_COUNT 4
-	xhci_isoch_transfer_t isoch_transfers[XHCI_ISOCH_BUFFER_COUNT];
+		/** Isochronous scheduled transfers with respective buffers */
+		#define XHCI_ISOCH_BUFFER_COUNT 4
+		xhci_isoch_transfer_t transfers[XHCI_ISOCH_BUFFER_COUNT];
 
-	/** Indices to transfers */
-	size_t isoch_dequeue, isoch_enqueue;
+		/** Indices to transfers */
+		size_t dequeue, enqueue;
 
-	/** Are isochronous transfers started? */
-	bool isoch_started;
+		/** Are isochronous transfers started? */
+		bool started;
 
-	/** Protects common buffers. */
-	fibril_mutex_t isoch_guard;
+		/** Protects common buffers. */
+		fibril_mutex_t guard;
 
-	/** Signals filled buffer. */
-	fibril_condvar_t isoch_avail;
-
+		/** Signals filled buffer. */
+		fibril_condvar_t avail;
+	} isoch [0];
 } xhci_endpoint_t;
 
Index: uspace/drv/bus/usb/xhci/transfers.c
===================================================================
--- uspace/drv/bus/usb/xhci/transfers.c	(revision bdd8842c8d5229ebdbb16f829986f5abb8cafae5)
+++ uspace/drv/bus/usb/xhci/transfers.c	(revision 17c5e62d0dbb1b04123131491f4743240d75deb7)
@@ -237,16 +237,16 @@
 
 static xhci_isoch_transfer_t* isoch_transfer_get_enqueue(xhci_endpoint_t *ep) {
-	if (((ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == ep->isoch_dequeue) {
+	if (((ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == ep->isoch->dequeue) {
 		/* None ready */
 		return NULL;
 	}
-	xhci_isoch_transfer_t *isoch_transfer = &ep->isoch_transfers[ep->isoch_enqueue];
-	ep->isoch_enqueue = (ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT;
+	xhci_isoch_transfer_t *isoch_transfer = &ep->isoch->transfers[ep->isoch->enqueue];
+	ep->isoch->enqueue = (ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT;
 	return isoch_transfer;
 }
 
 static xhci_isoch_transfer_t* isoch_transfer_get_dequeue(xhci_endpoint_t *ep) {
-	xhci_isoch_transfer_t *isoch_transfer = &ep->isoch_transfers[ep->isoch_dequeue];
-	ep->isoch_dequeue = (ep->isoch_dequeue + 1) % XHCI_ISOCH_BUFFER_COUNT;
+	xhci_isoch_transfer_t *isoch_transfer = &ep->isoch->transfers[ep->isoch->dequeue];
+	ep->isoch->dequeue = (ep->isoch->dequeue + 1) % XHCI_ISOCH_BUFFER_COUNT;
 	return isoch_transfer;
 }
@@ -283,8 +283,8 @@
 	xhci_trb_clean(&trb);
 
-	fibril_mutex_lock(&xhci_ep->isoch_guard);
+	fibril_mutex_lock(&xhci_ep->isoch->guard);
 	xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
 	while (!isoch_transfer) {
-		fibril_condvar_wait(&xhci_ep->isoch_avail, &xhci_ep->isoch_guard);
+		fibril_condvar_wait(&xhci_ep->isoch->avail, &xhci_ep->isoch->guard);
 		isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
 	}
@@ -301,5 +301,5 @@
 		&isoch_transfer->interrupt_trb_phys);
 	if (err) {
-		fibril_mutex_unlock(&xhci_ep->isoch_guard);
+		fibril_mutex_unlock(&xhci_ep->isoch->guard);
 		return err;
 	}
@@ -307,11 +307,11 @@
 	/* If not yet started, start the isochronous endpoint transfers - after buffer count - 1 writes */
 	/* The -1 is there because of the enqueue != dequeue check. The buffer must have at least 2 transfers. */
-	if (((xhci_ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == xhci_ep->isoch_dequeue && !xhci_ep->isoch_started) {
+	if (((xhci_ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == xhci_ep->isoch->dequeue && !xhci_ep->isoch->started) {
 		const uint8_t slot_id = xhci_dev->slot_id;
 		const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
 		err = hc_ring_doorbell(hc, slot_id, target);
-		xhci_ep->isoch_started = true;
-	}
-	fibril_mutex_unlock(&xhci_ep->isoch_guard);
+		xhci_ep->isoch->started = true;
+	}
+	fibril_mutex_unlock(&xhci_ep->isoch->guard);
 	if (err) {
 		return err;
@@ -331,5 +331,5 @@
 		xhci_trb_clean(&trb);
 		trb.parameter = isoch_transfer->data.phys;
-		isoch_transfer->size = xhci_ep->isoch_max_size;
+		isoch_transfer->size = xhci_ep->isoch->max_size;
 
 		int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size,
@@ -344,12 +344,12 @@
 	xhci_device_t *xhci_dev)
 {
-	fibril_mutex_lock(&xhci_ep->isoch_guard);
+	fibril_mutex_lock(&xhci_ep->isoch->guard);
 	/* If not yet started, start the isochronous endpoint transfers - before first read */
-	if (!xhci_ep->isoch_started) {
+	if (!xhci_ep->isoch->started) {
 		xhci_trb_ring_t *ring = get_ring(hc, transfer);
 		/* Fill the TRB ring. */
 		int err = schedule_isochronous_in_trbs(xhci_ep, ring);
 		if (err) {
-			fibril_mutex_unlock(&xhci_ep->isoch_guard);
+			fibril_mutex_unlock(&xhci_ep->isoch->guard);
 			return err;
 		}
@@ -359,13 +359,13 @@
 		err = hc_ring_doorbell(hc, slot_id, target);
 		if (err) {
-			fibril_mutex_unlock(&xhci_ep->isoch_guard);
+			fibril_mutex_unlock(&xhci_ep->isoch->guard);
 			return err;
 		}
-		xhci_ep->isoch_started = true;
+		xhci_ep->isoch->started = true;
 	}
 
 	xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
 	while(!isoch_transfer) {
-		fibril_condvar_wait(&xhci_ep->isoch_avail, &xhci_ep->isoch_guard);
+		fibril_condvar_wait(&xhci_ep->isoch->avail, &xhci_ep->isoch->guard);
 		isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
 	}
@@ -391,10 +391,10 @@
 
 	trb.parameter = isoch_transfer->data.phys;
-	isoch_transfer->size = xhci_ep->isoch_max_size;
+	isoch_transfer->size = xhci_ep->isoch->max_size;
 
 	xhci_trb_ring_t *ring = get_ring(hc, transfer);
 	int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size,
 		&isoch_transfer->interrupt_trb_phys);
-	fibril_mutex_unlock(&xhci_ep->isoch_guard);
+	fibril_mutex_unlock(&xhci_ep->isoch->guard);
 
 	if (err) {
@@ -411,5 +411,5 @@
 	xhci_device_t *xhci_dev)
 {
-	if (transfer->batch.buffer_size > xhci_ep->isoch_max_size) {
+	if (transfer->batch.buffer_size > xhci_ep->isoch->max_size) {
 		usb_log_error("Cannot schedule an oversized isochronous transfer.");
 		return EINVAL;
@@ -425,5 +425,5 @@
 
 static int handle_isochronous_transfer_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_endpoint_t *ep) {
-	fibril_mutex_lock(&ep->isoch_guard);
+	fibril_mutex_lock(&ep->isoch->guard);
 
 	int err = EOK;
@@ -434,8 +434,8 @@
 		case XHCI_TRBC_RING_UNDERRUN:
 			/* Rings are unscheduled by xHC now */
-			ep->isoch_started = false;
+			ep->isoch->started = false;
 			/* For OUT, there was nothing to process */
 			/* For IN, the buffer has overfilled, we empty the buffers and readd TRBs */
-			ep->isoch_enqueue = ep->isoch_dequeue = 0;
+			ep->isoch->enqueue = ep->isoch->dequeue = 0;
 			err = EIO;
 			break;
@@ -462,6 +462,6 @@
 	}
 
-	fibril_condvar_signal(&ep->isoch_avail);
-	fibril_mutex_unlock(&ep->isoch_guard);
+	fibril_condvar_signal(&ep->isoch->avail);
+	fibril_mutex_unlock(&ep->isoch->guard);
 	return err;
 }
Index: uspace/lib/usb/include/usb/descriptor.h
===================================================================
--- uspace/lib/usb/include/usb/descriptor.h	(revision bdd8842c8d5229ebdbb16f829986f5abb8cafae5)
+++ uspace/lib/usb/include/usb/descriptor.h	(revision 17c5e62d0dbb1b04123131491f4743240d75deb7)
@@ -217,8 +217,6 @@
 #define USB_ED_GET_ADD_OPPS(ed) \
 	((uint16_usb2host((ed).max_packet_size) >> 11) & 0x3)
-	/** Polling interval in milliseconds.
-	 * Ignored for bulk and control endpoints.
-	 * Isochronous endpoints must use value 1.
-	 * Interrupt endpoints any value from 1 to 255.
+	/** Polling interval. Different semantics for various (speed, type)
+	 * pairs.
 	 */
 	uint8_t poll_interval;
