When an isochronous transfer of n frames is scheduled, the last frame i.e. frame number (n - 1) is set to generate an interrupt.
To figure out which transfer generated the interrupt, the interrupt handler iterates over all outstanding transfers and checks if the last TD of the transfer is active. If it's not active, then the transter is done and the completion call-back is invoked. Except that for isochronous transfers the interrupt handler checks the n-th TD insted of the last one. In turn, the transfer appears as active and the completion call-back is not called (yet). It will be called on the interrupt of the next transfer (if any). OK? Index: uhci.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uhci.c,v retrieving revision 1.144 diff -u -p -u -p -r1.144 uhci.c --- uhci.c 16 Nov 2018 11:57:29 -0000 1.144 +++ uhci.c 7 Feb 2019 05:21:29 -0000 @@ -2188,7 +2188,7 @@ uhci_device_isoc_start(struct usbd_xfer #endif /* Find the last TD */ - i = ux->curframe + xfer->nframes; + i = ux->curframe + (xfer->nframes - 1); if (i >= UHCI_VFRAMELIST_COUNT) i -= UHCI_VFRAMELIST_COUNT; end = upipe->u.iso.stds[i];