Skip to content

Commit

Permalink
usb_libusb10.c: Keep track of dead transfers more correctly.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
zarvox committed Nov 20, 2011
1 parent a283a06 commit 75a3eb2
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions src/usb_libusb10.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,9 @@ static void iso_callback(struct libusb_transfer *xfer)
{
int i;
fnusb_isoc_stream *strm = (fnusb_isoc_stream*)xfer->user_data;
freenect_context *ctx = strm->parent->parent->parent;

if (strm->dead) {
freenect_context *ctx = strm->parent->parent->parent;
strm->dead_xfers++;
FN_SPEW("EP %02x transfer complete, %d left\n", xfer->endpoint, strm->num_xfers - strm->dead_xfers);
return;
Expand All @@ -437,23 +437,29 @@ static void iso_callback(struct libusb_transfer *xfer)
strm->cb(strm->parent->parent, buf, xfer->iso_packet_desc[i].actual_length);
buf += strm->len;
}
libusb_submit_transfer(xfer);
int res;
res = libusb_submit_transfer(xfer);
if (res != 0) {
FN_ERROR("iso_callback(): failed to resubmit transfer after successful completion: %d\n", res);
strm->dead_xfers++;
if (res == LIBUSB_TRANSFER_NO_DEVICE) {
fnusb_stop_iso(strm->parent, strm);
}
}
break;
}
case LIBUSB_TRANSFER_NO_DEVICE:
{
// We lost the device we were talking to. This is a large problem,
// and one that we should eventually come up with a way to
// properly propagate up to the caller.
freenect_context *ctx = strm->parent->parent->parent;
FN_ERROR("USB device disappeared, cancelling stream :(\n");
strm->dead_xfers++;
fnusb_stop_iso(strm->parent, strm);
break;
}
case LIBUSB_TRANSFER_CANCELLED:
{
freenect_context *ctx = strm->parent->parent->parent;
FN_SPEW("EP %02x transfer cancelled\n", xfer->endpoint);
strm->dead_xfers++;
break;
Expand All @@ -464,9 +470,16 @@ static void iso_callback(struct libusb_transfer *xfer)
// on OSX tends to hit random errors a lot. If we don't resubmit
// the transfers, eventually all of them die and then we don't get
// any more data from the Kinect.
freenect_context *ctx = strm->parent->parent->parent;
FN_WARNING("Isochronous transfer error: %d\n", xfer->status);
libusb_submit_transfer(xfer);
int res;
res = libusb_submit_transfer(xfer);
if (res != 0) {
FN_ERROR("Isochronous transfer resubmission failed after unknown error: %d\n", res);
strm->dead_xfers++;
if (res == LIBUSB_TRANSFER_NO_DEVICE) {
fnusb_stop_iso(strm->parent, strm);
}
}
break;
}
}
Expand Down

0 comments on commit 75a3eb2

Please sign in to comment.