Skip to content

Commit 75a3eb2

Browse files
committed
usb_libusb10.c: Keep track of dead transfers more correctly.
We failed to catch if the resubmission of a transfer failed in the transfer's isochronous callback. This is bad because this is a very likely failure mode if we accidentally unplug the Kinect - the last set of transfers complete successfully, but the device is no longer there when we resubmit them. It's okay for us to not know which particular transfers are dead, since libusb_cancel_transfer() will handle transfers that don't exist by returning LIBUSB_ERROR_NOT_FOUND if the transfer isn't pending. This is related to OpenKinect#229, but I'm not sure if this is sufficient to fix it. libusb on OSX doesn't always return what I expect it to. Signed-off-by: Drew Fisher <drew.m.fisher@gmail.com>
1 parent a283a06 commit 75a3eb2

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

src/usb_libusb10.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -421,9 +421,9 @@ static void iso_callback(struct libusb_transfer *xfer)
421421
{
422422
int i;
423423
fnusb_isoc_stream *strm = (fnusb_isoc_stream*)xfer->user_data;
424+
freenect_context *ctx = strm->parent->parent->parent;
424425

425426
if (strm->dead) {
426-
freenect_context *ctx = strm->parent->parent->parent;
427427
strm->dead_xfers++;
428428
FN_SPEW("EP %02x transfer complete, %d left\n", xfer->endpoint, strm->num_xfers - strm->dead_xfers);
429429
return;
@@ -437,23 +437,29 @@ static void iso_callback(struct libusb_transfer *xfer)
437437
strm->cb(strm->parent->parent, buf, xfer->iso_packet_desc[i].actual_length);
438438
buf += strm->len;
439439
}
440-
libusb_submit_transfer(xfer);
440+
int res;
441+
res = libusb_submit_transfer(xfer);
442+
if (res != 0) {
443+
FN_ERROR("iso_callback(): failed to resubmit transfer after successful completion: %d\n", res);
444+
strm->dead_xfers++;
445+
if (res == LIBUSB_TRANSFER_NO_DEVICE) {
446+
fnusb_stop_iso(strm->parent, strm);
447+
}
448+
}
441449
break;
442450
}
443451
case LIBUSB_TRANSFER_NO_DEVICE:
444452
{
445453
// We lost the device we were talking to. This is a large problem,
446454
// and one that we should eventually come up with a way to
447455
// properly propagate up to the caller.
448-
freenect_context *ctx = strm->parent->parent->parent;
449456
FN_ERROR("USB device disappeared, cancelling stream :(\n");
450457
strm->dead_xfers++;
451458
fnusb_stop_iso(strm->parent, strm);
452459
break;
453460
}
454461
case LIBUSB_TRANSFER_CANCELLED:
455462
{
456-
freenect_context *ctx = strm->parent->parent->parent;
457463
FN_SPEW("EP %02x transfer cancelled\n", xfer->endpoint);
458464
strm->dead_xfers++;
459465
break;
@@ -464,9 +470,16 @@ static void iso_callback(struct libusb_transfer *xfer)
464470
// on OSX tends to hit random errors a lot. If we don't resubmit
465471
// the transfers, eventually all of them die and then we don't get
466472
// any more data from the Kinect.
467-
freenect_context *ctx = strm->parent->parent->parent;
468473
FN_WARNING("Isochronous transfer error: %d\n", xfer->status);
469-
libusb_submit_transfer(xfer);
474+
int res;
475+
res = libusb_submit_transfer(xfer);
476+
if (res != 0) {
477+
FN_ERROR("Isochronous transfer resubmission failed after unknown error: %d\n", res);
478+
strm->dead_xfers++;
479+
if (res == LIBUSB_TRANSFER_NO_DEVICE) {
480+
fnusb_stop_iso(strm->parent, strm);
481+
}
482+
}
470483
break;
471484
}
472485
}

0 commit comments

Comments
 (0)