Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision 7d957b20978eb7a4e4741ee6fbda6c0e33c08ddf)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision 6455d39e0502427e5c374bc86c13191c94b14f51)
@@ -83,4 +83,7 @@
 		ep->isoch_dequeue = XHCI_ISOCH_BUFFER_COUNT - 1;
 		ep->isoch_started = false;
+
+		fibril_mutex_initialize(&ep->isoch_guard);
+		fibril_condvar_initialize(&ep->isoch_avail);
 	}
 
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision 7d957b20978eb7a4e4741ee6fbda6c0e33c08ddf)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision 6455d39e0502427e5c374bc86c13191c94b14f51)
@@ -102,4 +102,11 @@
 	/** Are isochronous transfers started? */
 	bool isoch_started;
+
+	/** Protects common buffers. */
+	fibril_mutex_t isoch_guard;
+
+	/** Signals filled buffer. */
+	fibril_condvar_t isoch_avail;
+
 } xhci_endpoint_t;
 
Index: uspace/drv/bus/usb/xhci/transfers.c
===================================================================
--- uspace/drv/bus/usb/xhci/transfers.c	(revision 7d957b20978eb7a4e4741ee6fbda6c0e33c08ddf)
+++ uspace/drv/bus/usb/xhci/transfers.c	(revision 6455d39e0502427e5c374bc86c13191c94b14f51)
@@ -280,8 +280,9 @@
 	xhci_trb_clean(&trb);
 
-	// FIXME add some locks
+	fibril_mutex_lock(&xhci_ep->isoch_guard);
 	xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
 	while (!isoch_transfer) {
-		// FIXME: add condvar sleep;
+		fibril_condvar_wait(&xhci_ep->isoch_avail, &xhci_ep->isoch_guard);
+		isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
 	}
 
@@ -297,4 +298,5 @@
 		&isoch_transfer->interrupt_trb_phys);
 	if (err) {
+		fibril_mutex_unlock(&xhci_ep->isoch_guard);
 		return err;
 	}
@@ -306,8 +308,9 @@
 		const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */
 		err = hc_ring_doorbell(hc, slot_id, target);
-		if (err) {
-			return err;
-		}
 		xhci_ep->isoch_started = true;
+	}
+	fibril_mutex_unlock(&xhci_ep->isoch_guard);
+	if (err) {
+		return err;
 	}
 
@@ -322,4 +325,5 @@
 	xhci_device_t *xhci_dev)
 {
+	fibril_mutex_lock(&xhci_ep->isoch_guard);
 	/* If not yet started, start the isochronous endpoint transfers - before first read */
 	if (!xhci_ep->isoch_started) {
@@ -328,4 +332,5 @@
 		int err = hc_ring_doorbell(hc, slot_id, target);
 		if (err) {
+			fibril_mutex_unlock(&xhci_ep->isoch_guard);
 			return err;
 		}
@@ -333,8 +338,8 @@
 	}
 
-	// FIXME add some locks
 	xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
 	while(!isoch_transfer) {
-		// FIXME: add condvar sleep;
+		fibril_condvar_wait(&xhci_ep->isoch_avail, &xhci_ep->isoch_guard);
+		isoch_transfer = isoch_transfer_get_enqueue(xhci_ep);
 	}
 
@@ -364,4 +369,6 @@
 	int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size,
 		&isoch_transfer->interrupt_trb_phys);
+	fibril_mutex_unlock(&xhci_ep->isoch_guard);
+
 	if (err) {
 		return err;
@@ -391,5 +398,25 @@
 
 static int handle_isochronous_transfer_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_endpoint_t *ep) {
-	fibril_mutex_lock(&ep->base.guard);
+	fibril_mutex_lock(&ep->isoch_guard);
+
+	int err = EOK;
+
+	const xhci_trb_completion_code_t completion_code = TRB_COMPLETION_CODE(*trb);
+	switch (completion_code) {
+		case XHCI_TRBC_RING_OVERRUN:
+		case XHCI_TRBC_RING_UNDERRUN:
+			// TODO: abort the phone; rings are unscheduled by xHC by now
+			ep->isoch_started = false;
+			err = EIO;
+			break;
+		case XHCI_TRBC_SHORT_PACKET:
+			usb_log_debug("Short transfer.");
+			/* fallthrough */
+		case XHCI_TRBC_SUCCESS:
+			break;
+		default:
+			usb_log_warning("Transfer not successfull: %u", completion_code);
+			err = EIO;
+	}
 
 	xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_dequeue(ep);
@@ -397,5 +424,5 @@
 		usb_log_error("Non-matching trb to isochronous transfer, skipping.");
 		// FIXME: what to do? probably just kill the whole endpoint
-		return ENOENT;
+		err = ENOENT;
 	}
 
@@ -405,8 +432,7 @@
 	}
 
-	// TODO: Send notify to waiting fibrils in case they are waiting here
-
-	fibril_mutex_unlock(&ep->base.guard);
-	return EOK;
+	fibril_condvar_signal(&ep->isoch_avail);
+	fibril_mutex_unlock(&ep->isoch_guard);
+	return err;
 }
 
