Index: lib/libusb/libusb10.c =================================================================== --- lib/libusb/libusb10.c (revision 338540) +++ lib/libusb/libusb10.c (working copy) @@ -114,6 +114,19 @@ fcntl(f, F_SETFL, flags); } +static void +libusb10_wakeup_event_loop(libusb_context *ctx) +{ + uint8_t dummy = 0; + int err; + + err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); + if (err < (int)sizeof(dummy)) { + /* ignore error, if any */ + DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "Waking up event loop failed!"); + } +} + int libusb_init(libusb_context **context) { @@ -484,7 +497,6 @@ { libusb_context *ctx = dev->ctx; struct libusb20_device *pdev = dev->os_priv; - uint8_t dummy; int err; if (devh == NULL) @@ -506,12 +518,8 @@ POLLOUT | POLLRDNORM | POLLWRNORM); /* make sure our event loop detects the new device */ - dummy = 0; - err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); - if (err < (int)sizeof(dummy)) { - /* ignore error, if any */ - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_open write failed!"); - } + libusb10_wakeup_event_loop(ctx); + *devh = pdev; return (0); @@ -564,8 +572,6 @@ { libusb_context *ctx; struct libusb_device *dev; - uint8_t dummy; - int err; if (pdev == NULL) return; /* be NULL safe */ @@ -581,12 +587,7 @@ libusb_unref_device(dev); /* make sure our event loop detects the closed device */ - dummy = 0; - err = write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); - if (err < (int)sizeof(dummy)) { - /* ignore error, if any */ - DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_close write failed!"); - } + libusb10_wakeup_event_loop(ctx); } libusb_device * @@ -1314,7 +1315,6 @@ int buffsize; int maxframe; int temp; - uint8_t dummy; dev = libusb_get_device(pdev); @@ -1415,10 +1415,8 @@ failure: libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_ERROR); - /* make sure our event loop spins the done handler */ - dummy = 0; - err = write(dev->ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); + libusb10_wakeup_event_loop(dev->ctx); } /* The following function must be called unlocked */ @@ -1490,6 +1488,7 @@ struct libusb20_transfer *pxfer1; struct libusb_super_transfer *sxfer; struct libusb_device *dev; + struct libusb_device_handle *devh; uint8_t endpoint; int retval; @@ -1497,12 +1496,12 @@ return (LIBUSB_ERROR_INVALID_PARAM); /* check if not initialised */ - if (uxfer->dev_handle == NULL) + if ((devh = uxfer->dev_handle) == NULL) return (LIBUSB_ERROR_NOT_FOUND); endpoint = uxfer->endpoint; - dev = libusb_get_device(uxfer->dev_handle); + dev = libusb_get_device(devh); DPRINTF(dev->ctx, LIBUSB_DEBUG_FUNCTION, "libusb_cancel_transfer enter"); @@ -1513,8 +1512,8 @@ CTX_LOCK(dev->ctx); - pxfer0 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 0); - pxfer1 = libusb10_get_transfer(uxfer->dev_handle, endpoint, 1); + pxfer0 = libusb10_get_transfer(devh, endpoint, 0); + pxfer1 = libusb10_get_transfer(devh, endpoint, 1); if (sxfer->state != LIBUSB_SUPER_XFER_ST_PEND) { /* only update the transfer status */ @@ -1526,6 +1525,8 @@ sxfer->entry.tqe_prev = NULL; libusb10_complete_transfer(NULL, sxfer, LIBUSB_TRANSFER_CANCELLED); + /* make sure our event loop spins the done handler */ + libusb10_wakeup_event_loop(dev->ctx); } else if (pxfer0 == NULL || pxfer1 == NULL) { /* not started */ retval = LIBUSB_ERROR_NOT_FOUND; @@ -1532,17 +1533,30 @@ } else if (libusb20_tr_get_priv_sc1(pxfer0) == sxfer) { libusb10_complete_transfer(pxfer0, sxfer, LIBUSB_TRANSFER_CANCELLED); - libusb20_tr_stop(pxfer0); - /* make sure the queue doesn't stall */ - libusb10_submit_transfer_sub( - uxfer->dev_handle, endpoint); + if (libusb20_dev_check_connected(devh)) { + /* clear transfer pointer */ + libusb20_tr_set_priv_sc1(pxfer0, NULL); + /* make sure our event loop spins the done handler */ + libusb10_wakeup_event_loop(dev->ctx); + } else { + libusb20_tr_stop(pxfer0); + /* make sure the queue doesn't stall */ + libusb10_submit_transfer_sub(devh, endpoint); + } } else if (libusb20_tr_get_priv_sc1(pxfer1) == sxfer) { libusb10_complete_transfer(pxfer1, sxfer, LIBUSB_TRANSFER_CANCELLED); - libusb20_tr_stop(pxfer1); - /* make sure the queue doesn't stall */ - libusb10_submit_transfer_sub( - uxfer->dev_handle, endpoint); + /* check if handle is still active */ + if (libusb20_dev_check_connected(devh)) { + /* clear transfer pointer */ + libusb20_tr_set_priv_sc1(pxfer1, NULL); + /* make sure our event loop spins the done handler */ + libusb10_wakeup_event_loop(dev->ctx); + } else { + libusb20_tr_stop(pxfer1); + /* make sure the queue doesn't stall */ + libusb10_submit_transfer_sub(devh, endpoint); + } } else { /* not started */ retval = LIBUSB_ERROR_NOT_FOUND; Index: lib/libusb/libusb10_io.c =================================================================== --- lib/libusb/libusb10_io.c (revision 338540) +++ lib/libusb/libusb10_io.c (working copy) @@ -161,17 +161,13 @@ if (ppdev[i] != NULL) { dev = libusb_get_device(ppdev[i]); - if (fds[i].revents == 0) - err = 0; /* nothing to do */ - else + if (fds[i].revents != 0) { err = libusb20_dev_process(ppdev[i]); - if (err) { - /* cancel all transfers - device is gone */ - libusb10_cancel_all_transfer(dev); - - /* remove USB device from polling loop */ - libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); + if (err) { + /* remove USB device from polling loop */ + libusb10_remove_pollfd(dev->ctx, &dev->dev_poll); + } } CTX_UNLOCK(ctx); libusb_unref_device(dev); @@ -180,10 +176,8 @@ } else { uint8_t dummy; - while (1) { - if (read(fds[i].fd, &dummy, 1) != 1) - break; - } + while (read(fds[i].fd, &dummy, 1) == 1) + ; } }