static int haiku_handle_transfer_completion(struct usbi_transfer * itransfer) { USBTransfer* transfer=*((USBTransfer**)usbi_transfer_get_os_priv(itransfer)); usbi_mutex_lock(&itransfer->lock); if(transfer->IsCancelled()) { delete transfer; *((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL; usbi_mutex_unlock(&itransfer->lock); if (itransfer->transferred < 0) itransfer->transferred = 0; return usbi_handle_transfer_cancellation(itransfer); } libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; if(itransfer->transferred < 0) { usbi_err(ITRANSFER_CTX(itransfer), "error in transfer"); status = LIBUSB_TRANSFER_ERROR; itransfer->transferred=0; } delete transfer; *((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL; usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, status); }
int obsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds, int num_ready) { struct libusb_device_handle *handle; struct handle_priv *hpriv = NULL; struct usbi_transfer *itransfer; struct pollfd *pollfd; int i, err = 0; usbi_dbg(""); pthread_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { pollfd = &fds[i]; if (!pollfd->revents) continue; hpriv = NULL; num_ready--; list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { hpriv = (struct handle_priv *)handle->os_priv; if (hpriv->pipe[0] == pollfd->fd) break; hpriv = NULL; } if (NULL == hpriv) { usbi_dbg("fd %d is not an event pipe!", pollfd->fd); err = ENOENT; break; } if (pollfd->revents & POLLERR) { usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]); usbi_handle_disconnect(handle); continue; } if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) { err = errno; break; } if ((err = usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED))) break; } pthread_mutex_unlock(&ctx->open_devs_lock); if (err) return _errno_to_libusb(err); return (LIBUSB_SUCCESS); }
static void windows_transfer_callback(const struct windows_backend *backend, struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size) { int status, istatus; usbi_dbg("handling I/O completion with errcode %u, size %u", (unsigned int)io_result, (unsigned int)io_size); switch (io_result) { case NO_ERROR: status = backend->copy_transfer_data(itransfer, (uint32_t)io_size); break; case ERROR_GEN_FAILURE: usbi_dbg("detected endpoint stall"); status = LIBUSB_TRANSFER_STALL; break; case ERROR_SEM_TIMEOUT: usbi_dbg("detected semaphore timeout"); status = LIBUSB_TRANSFER_TIMED_OUT; break; case ERROR_OPERATION_ABORTED: istatus = backend->copy_transfer_data(itransfer, (uint32_t)io_size); if (istatus != LIBUSB_TRANSFER_COMPLETED) usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); usbi_dbg("detected operation aborted"); status = LIBUSB_TRANSFER_CANCELLED; break; case ERROR_FILE_NOT_FOUND: usbi_dbg("detected device removed"); status = LIBUSB_TRANSFER_NO_DEVICE; break; default: usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", (unsigned int)io_result, windows_error_str(io_result)); status = LIBUSB_TRANSFER_ERROR; break; } backend->clear_transfer_priv(itransfer); // Cancel polling if (status == LIBUSB_TRANSFER_CANCELLED) usbi_handle_transfer_cancellation(itransfer); else usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); }
static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) { int status, istatus; usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size); switch (io_result) { case NO_ERROR: status = windows_copy_transfer_data(itransfer, io_size); break; case ERROR_GEN_FAILURE: usbi_dbg("detected endpoint stall"); status = LIBUSB_TRANSFER_STALL; break; case ERROR_SEM_TIMEOUT: usbi_dbg("detected semaphore timeout"); status = LIBUSB_TRANSFER_TIMED_OUT; break; case ERROR_OPERATION_ABORTED: istatus = windows_copy_transfer_data(itransfer, io_size); if (istatus != LIBUSB_TRANSFER_COMPLETED) usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus); if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) { usbi_dbg("detected timeout"); status = LIBUSB_TRANSFER_TIMED_OUT; } else { usbi_dbg("detected operation aborted"); status = LIBUSB_TRANSFER_CANCELLED; } break; default: usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result)); status = LIBUSB_TRANSFER_ERROR; break; } windows_clear_transfer_priv(itransfer); // Cancel polling usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); }
static int solaris_submit_ctrl_on_default(struct libusb_transfer *transfer) { int ret = -1, setup_ret; int status; sunos_dev_handle_priv_t *hpriv; struct libusb_device_handle *hdl = transfer->dev_handle; uint16_t wLength; uint8_t *data = transfer->buffer; hpriv = (sunos_dev_handle_priv_t *)hdl->os_priv; wLength = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; if (hpriv->eps[0].datafd == -1) { usbi_dbg("ep0 not opened"); return (LIBUSB_ERROR_NOT_FOUND); } if ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { usbi_dbg("IN request"); ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd, (char *)data, LIBUSB_CONTROL_SETUP_SIZE, WRITE, (int *)&status); } else { usbi_dbg("OUT request"); ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd, transfer->buffer, transfer->length, WRITE, (int *)&transfer->status); } setup_ret = ret; if (ret < LIBUSB_CONTROL_SETUP_SIZE) { usbi_dbg("error sending control msg: %d", ret); return (LIBUSB_ERROR_IO); } ret = transfer->length - LIBUSB_CONTROL_SETUP_SIZE; /* Read the remaining bytes for IN request */ if ((wLength) && ((data[0] & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)) { usbi_dbg("DATA: %d", transfer->length - setup_ret); ret = usb_do_io(hpriv->eps[0].datafd, hpriv->eps[0].statfd, (char *)transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, wLength, READ, (int *)&transfer->status); } if (ret >= 0) { transfer->actual_length = ret; LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)->transferred = ret; } usbi_dbg("Done: ctrl data bytes %d", ret); /* sync transfer handling */ ret = usbi_handle_transfer_completion(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer), transfer->status); return (ret); }
int sunos_handle_transfer_completion(struct usbi_transfer *itransfer) { return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); }
static void wince_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); int status; usbi_dbg("handling I/O completion with errcode %d", io_result); if (io_result == ERROR_NOT_SUPPORTED && transfer->type != LIBUSB_TRANSFER_TYPE_CONTROL) { /* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper * Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the * endpoint isn't actually stalled. * * One example of this is that some devices will occasionally fail to reply to an IN * token. The WinCE USB layer carries on with the transaction until it is completed * (or cancelled) but then completes it with USB_ERROR_STALL. * * This code therefore needs to confirm that there really is a stall error, by both * checking the pipe status and requesting the endpoint status from the device. */ BOOL halted = FALSE; usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall"); if (UkwIsPipeHalted(priv->dev, transfer->endpoint, &halted)) { /* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS * control request to the device. This is done synchronously, which is a bit * naughty, but this is a special corner case. */ WORD wStatus = 0; DWORD written = 0; UKW_CONTROL_HEADER ctrlHeader; ctrlHeader.bmRequestType = LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_ENDPOINT; ctrlHeader.bRequest = LIBUSB_REQUEST_GET_STATUS; ctrlHeader.wValue = 0; ctrlHeader.wIndex = transfer->endpoint; ctrlHeader.wLength = sizeof(wStatus); if (UkwIssueControlTransfer(priv->dev, UKW_TF_IN_TRANSFER | UKW_TF_SEND_TO_ENDPOINT, &ctrlHeader, &wStatus, sizeof(wStatus), &written, NULL)) { if (written == sizeof(wStatus) && (wStatus & STATUS_HALT_FLAG) == 0) { if (!halted || UkwClearHaltHost(priv->dev, transfer->endpoint)) { usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success"); io_result = ERROR_SUCCESS; } else { usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error"); io_result = ERROR_IO_DEVICE; } } } } } switch(io_result) { case ERROR_SUCCESS: itransfer->transferred += io_size; status = LIBUSB_TRANSFER_COMPLETED; break; case ERROR_CANCELLED: usbi_dbg("detected transfer cancel"); status = LIBUSB_TRANSFER_CANCELLED; break; case ERROR_NOT_SUPPORTED: case ERROR_GEN_FAILURE: usbi_dbg("detected endpoint stall"); status = LIBUSB_TRANSFER_STALL; break; case ERROR_SEM_TIMEOUT: usbi_dbg("detected semaphore timeout"); status = LIBUSB_TRANSFER_TIMED_OUT; break; case ERROR_OPERATION_ABORTED: if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) { usbi_dbg("detected timeout"); status = LIBUSB_TRANSFER_TIMED_OUT; } else { usbi_dbg("detected operation aborted"); status = LIBUSB_TRANSFER_CANCELLED; } break; default: usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result)); status = LIBUSB_TRANSFER_ERROR; break; } wince_clear_transfer_priv(itransfer); if (status == LIBUSB_TRANSFER_CANCELLED) { usbi_handle_transfer_cancellation(itransfer); } else { usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); } }