usbi_dbg("transfer %p", transfer);
usbi_mutex_lock(&ctx->flying_transfers_lock);
usbi_mutex_lock(&itransfer->lock);
+ if (itransfer->flags & USBI_TRANSFER_IN_FLIGHT) {
+ r = LIBUSB_ERROR_BUSY;
+ goto out;
+ }
itransfer->transferred = 0;
itransfer->flags = 0;
r = calculate_timeout(itransfer);
list_del(&itransfer->list);
arm_timerfd_for_next_timeout(ctx);
} else {
+ itransfer->flags |= USBI_TRANSFER_IN_FLIGHT;
/* keep a reference to this device */
libusb_ref_device(transfer->dev_handle->dev);
}
*
* \param transfer the transfer to cancel
* \returns 0 on success
- * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is already complete or
- * cancelled.
+ * \returns LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress,
+ * already complete, or already cancelled.
* \returns a LIBUSB_ERROR code on failure
*/
int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
usbi_dbg("transfer %p", transfer );
usbi_mutex_lock(&itransfer->lock);
+ if (!(itransfer->flags & USBI_TRANSFER_IN_FLIGHT)
+ || (itransfer->flags & USBI_TRANSFER_CANCELLING)) {
+ r = LIBUSB_ERROR_NOT_FOUND;
+ goto out;
+ }
r = usbi_backend->cancel_transfer(itransfer);
if (r < 0) {
if (r != LIBUSB_ERROR_NOT_FOUND &&
itransfer->flags |= USBI_TRANSFER_CANCELLING;
+out:
usbi_mutex_unlock(&itransfer->lock);
return r;
}
if (usbi_using_timerfd(ctx) && (r < 0))
return r;
+ usbi_mutex_lock(&itransfer->lock);
+ itransfer->flags &= ~USBI_TRANSFER_IN_FLIGHT;
+ usbi_mutex_unlock(&itransfer->lock);
+
if (status == LIBUSB_TRANSFER_COMPLETED
&& transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) {
int rqlen = transfer->length;
int i;
size_t alloc_size;
- if (tpriv->urbs)
- return LIBUSB_ERROR_BUSY;
-
if (is_out && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) &&
!(dpriv->caps & USBFS_CAP_ZERO_PACKET))
return LIBUSB_ERROR_NOT_SUPPORTED;
unsigned int packet_len;
unsigned char *urb_buffer = transfer->buffer;
- if (tpriv->iso_urbs)
- return LIBUSB_ERROR_BUSY;
-
/* usbfs places a 32kb limit on iso URBs. we divide up larger requests
* into smaller units to meet such restriction, then fire off all the
* units at once. it would be simpler if we just fired one unit at a time,
struct usbfs_urb *urb;
int r;
- if (tpriv->urbs)
- return LIBUSB_ERROR_BUSY;
-
if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH)
return LIBUSB_ERROR_INVALID_PARAM;