static int haiku_cancel_transfer(struct usbi_transfer * itransfer) { struct libusb_transfer* fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); USBDeviceHandle * fDeviceHandle = *((USBDeviceHandle**)fLibusbTransfer->dev_handle->os_priv); return fDeviceHandle->CancelTransfer(*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))); }
void windows_get_overlapped_result(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size) { if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first || GetOverlappedResult(pollable_fd->handle, pollable_fd->overlapped, io_size, false)) { // Regular async overlapped struct libusb_transfer *ltransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(transfer); if (ltransfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { int i; for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) { struct libusb_iso_packet_descriptor *lib_desc = <ransfer->iso_packet_desc[i]; switch (transfer_priv->IsochronousResultsArray[i].TransferResult) { case STATUS_SUCCESS: case STATUS_CANCELLED: case STATUS_REQUEST_CANCELED: lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS break; default: lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION; break; } lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength; } } *io_size = (DWORD) transfer_priv->request.Result.GenResult.BytesTransferred; *io_result = usbdk_translate_usbd_status((USBD_STATUS) transfer_priv->request.Result.GenResult.UsbdStatus); } else { *io_result = GetLastError(); } }
int sunos_cancel_transfer(struct usbi_transfer *itransfer) { sunos_xfer_priv_t *tpriv; sunos_dev_handle_priv_t *hpriv; struct libusb_transfer *transfer; struct aiocb *aiocb; uint8_t ep; int ret; tpriv = usbi_transfer_get_os_priv(itransfer); aiocb = &tpriv->aiocb; transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; ep = sunos_usb_ep_index(transfer->endpoint); ret = aio_cancel(hpriv->eps[ep].datafd, aiocb); usbi_dbg("aio->fd=%d fd=%d ret = %d, %s", aiocb->aio_fildes, hpriv->eps[ep].datafd, ret, (ret == AIO_CANCELED)? strerror(0):strerror(errno)); if (ret != AIO_CANCELED) { ret = _errno_to_libusb(errno); } else { /* * we don't need to call usbi_handle_transfer_cancellation(), * because we'll handle everything in sunos_async_callback. */ ret = LIBUSB_SUCCESS; } return (ret); }
static int haiku_submit_transfer(struct usbi_transfer * itransfer) { struct libusb_transfer* fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); USBDeviceHandle * fDeviceHandle = *((USBDeviceHandle**)fLibusbTransfer->dev_handle->os_priv); return fDeviceHandle->SubmitTransfer(itransfer); }
int _sync_gen_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer; int fd, nr = 1; transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); if ((fd = _access_endpoint(transfer)) < 0) return _errno_to_libusb(errno); if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) return _errno_to_libusb(errno); if (IS_XFERIN(transfer)) { if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) return _errno_to_libusb(errno); nr = read(fd, transfer->buffer, transfer->length); } else { nr = write(fd, transfer->buffer, transfer->length); } if (nr < 0) return _errno_to_libusb(errno); itransfer->transferred = nr; return (0); }
static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); 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); BOOL direction_in, ret; struct winfd wfd; DWORD flags; HANDLE eventHandle; PUKW_CONTROL_HEADER setup = NULL; const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL; transfer_priv->pollable_fd = INVALID_WINFD; if (control_transfer) { setup = (PUKW_CONTROL_HEADER) transfer->buffer; direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN; } else { direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; } flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER; flags |= UKW_TF_SHORT_TRANSFER_OK; eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); if (eventHandle == NULL) { usbi_err(ctx, "Failed to create event for async transfer"); return LIBUSB_ERROR_NO_MEM; } wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer); if (wfd.fd < 0) { CloseHandle(eventHandle); return LIBUSB_ERROR_NO_MEM; } transfer_priv->pollable_fd = wfd; if (control_transfer) { // Split out control setup header and data buffer DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER); PVOID buf = (PVOID) &transfer->buffer[sizeof(UKW_CONTROL_HEADER)]; ret = UkwIssueControlTransfer(priv->dev, flags, setup, buf, bufLen, &transfer->actual_length, wfd.overlapped); } else { ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer, transfer->length, &transfer->actual_length, wfd.overlapped); } if (!ret) { int libusbErr = translate_driver_error(GetLastError()); usbi_err(ctx, "UkwIssue%sTransfer failed: error %d", control_transfer ? "Control" : "Bulk", GetLastError()); wince_clear_transfer_priv(itransfer); return libusbErr; } usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT); itransfer->flags |= USBI_TRANSFER_UPDATED_FDS; return LIBUSB_SUCCESS; }
static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct winfd wfd; TransferResult transferRes; HANDLE sysHandle; transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.EndpointAddress = transfer->endpoint; switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_BULK: transfer_priv->request.TransferType = BulkTransferType; break; case LIBUSB_TRANSFER_TYPE_INTERRUPT: transfer_priv->request.TransferType = IntertuptTransferType; break; default: usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer. %s", transfer->type, windows_error_str(0)); return LIBUSB_ERROR_INVALID_PARAM; } transfer_priv->pollable_fd = INVALID_WINFD; sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); // Always use the handle returned from usbi_create_fd (wfd.handle) if (wfd.fd < 0) return LIBUSB_ERROR_NO_MEM; if (IS_XFERIN(transfer)) transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); else transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); switch (transferRes) { case TransferSuccess: wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; break; case TransferSuccessAsync: break; case TransferFailure: usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; } transfer_priv->pollable_fd = wfd; usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); return LIBUSB_SUCCESS; }
static int wince_cancel_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer); if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT)) return translate_driver_error(GetLastError()); return LIBUSB_SUCCESS; }
void windows_clear_transfer_priv(struct usbi_transfer *itransfer) { struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); usbi_free_fd(&transfer_priv->pollable_fd); if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { safe_free(transfer_priv->IsochronousPacketsArray); safe_free(transfer_priv->IsochronousResultsArray); } }
static int usbdk_abort_transfers(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); return LIBUSB_ERROR_NO_DEVICE; } return LIBUSB_SUCCESS; }
static void do_close(struct libusb_context *ctx, struct libusb_device_handle *dev_handle) { struct usbi_transfer *itransfer; struct usbi_transfer *tmp; libusb_lock_events(ctx); usbi_mutex_lock(&ctx->flying_transfers_lock); list_for_each_entry_safe(itransfer, tmp, &ctx->flying_transfers, list, struct usbi_transfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); if (transfer->dev_handle != dev_handle) continue; if (!(itransfer->flags & USBI_TRANSFER_DEVICE_DISAPPEARED)) { usbi_err(ctx, "Device handle closed while transfer was still being processed, but the device is still connected as far as we know"); if (itransfer->flags & USBI_TRANSFER_CANCELLING) usbi_warn(ctx, "A cancellation for an in-flight transfer hasn't completed but closing the device handle"); else usbi_err(ctx, "A cancellation hasn't even been scheduled on the transfer for which the device is closing"); } usbi_mutex_lock(&itransfer->lock); list_del(&itransfer->list); transfer->dev_handle = NULL; usbi_mutex_unlock(&itransfer->lock); usbi_dbg("Removed transfer %p from the in-flight list because device handle %p closed", transfer, dev_handle); } usbi_mutex_unlock(&ctx->flying_transfers_lock); libusb_unlock_events(ctx); usbi_mutex_lock(&ctx->open_devs_lock); list_del(&dev_handle->list); usbi_mutex_unlock(&ctx->open_devs_lock); usbi_backend->close(dev_handle); libusb_unref_device(dev_handle->dev); usbi_mutex_destroy(&dev_handle->lock); free(dev_handle); }
int sunos_submit_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer; struct libusb_device_handle *hdl; int err = 0; transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); hdl = transfer->dev_handle; err = sunos_check_device_and_status_open(hdl, transfer->endpoint, transfer->type); if (err < 0) { return (_errno_to_libusb(err)); } switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: /* sync transfer */ usbi_dbg("CTRL transfer: %d", transfer->length); err = solaris_submit_ctrl_on_default(transfer); break; case LIBUSB_TRANSFER_TYPE_BULK: /* fallthru */ case LIBUSB_TRANSFER_TYPE_INTERRUPT: if (transfer->type == LIBUSB_TRANSFER_TYPE_BULK) usbi_dbg("BULK transfer: %d", transfer->length); else usbi_dbg("INTR transfer: %d", transfer->length); err = sunos_do_async_io(transfer); break; case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: /* Isochronous/Stream is not supported */ /* fallthru */ case LIBUSB_TRANSFER_TYPE_BULK_STREAM: if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) usbi_dbg("ISOC transfer: %d", transfer->length); else usbi_dbg("BULK STREAM transfer: %d", transfer->length); err = LIBUSB_ERROR_NOT_SUPPORTED; break; } return (err); }
static void wince_handle_callback (struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: wince_transfer_callback (itransfer, io_result, io_size); break; default: usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); } }
static int usbdk_do_control_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct winfd wfd; ULONG Length; TransferResult transResult; HANDLE sysHandle; sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); wfd = usbi_create_fd(sysHandle, RW_READ, NULL, NULL); // Always use the handle returned from usbi_create_fd (wfd.handle) if (wfd.fd < 0) return LIBUSB_ERROR_NO_MEM; transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.TransferType = ControlTransferType; transfer_priv->pollable_fd = INVALID_WINFD; Length = (ULONG)transfer->length; if (IS_XFERIN(transfer)) transResult = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); else transResult = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); switch (transResult) { case TransferSuccess: wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; wfd.overlapped->InternalHigh = (DWORD)Length; break; case TransferSuccessAsync: break; case TransferFailure: usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0)); usbi_free_fd(&wfd); return LIBUSB_ERROR_IO; } // Use priv_transfer to store data needed for async polling transfer_priv->pollable_fd = wfd; usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN); return LIBUSB_SUCCESS; }
int obsd_submit_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer; struct handle_priv *hpriv; int err = 0; usbi_dbg(""); transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: err = _sync_control_transfer(itransfer); break; case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: if (IS_XFEROUT(transfer)) { /* Isochronous write is not supported */ err = LIBUSB_ERROR_NOT_SUPPORTED; break; } err = _sync_gen_transfer(itransfer); break; case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: if (IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) { err = LIBUSB_ERROR_NOT_SUPPORTED; break; } err = _sync_gen_transfer(itransfer); break; case LIBUSB_TRANSFER_TYPE_BULK_STREAM: err = LIBUSB_ERROR_NOT_SUPPORTED; break; } if (err) return (err); if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0) return _errno_to_libusb(errno); return (LIBUSB_SUCCESS); }
static int wince_submit_transfer( struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: return wince_submit_control_or_bulk_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return wince_submit_iso_transfer(itransfer); default: usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } }
void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: windows_transfer_callback(itransfer, io_result, io_size); break; case LIBUSB_TRANSFER_TYPE_BULK_STREAM: usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform"); break; default: usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); } }
static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: // Control transfers cancelled by IoCancelXXX() API // No special treatment needed return LIBUSB_SUCCESS; case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return usbdk_abort_transfers(itransfer); default: usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } }
static int usbdk_submit_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); switch (transfer->type) { case LIBUSB_TRANSFER_TYPE_CONTROL: return usbdk_do_control_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_BULK: case LIBUSB_TRANSFER_TYPE_INTERRUPT: if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)) return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk else return usbdk_do_bulk_transfer(itransfer); case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return usbdk_do_iso_transfer(itransfer); default: usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } }
int _sync_control_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer; struct libusb_control_setup *setup; struct device_priv *dpriv; struct usb_ctl_request req; transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; setup = (struct libusb_control_setup *)transfer->buffer; usbi_dbg("type %d request %d value %d index %d length %d timeout %d", setup->bmRequestType, setup->bRequest, libusb_le16_to_cpu(setup->wValue), libusb_le16_to_cpu(setup->wIndex), libusb_le16_to_cpu(setup->wLength), transfer->timeout); req.ucr_request.bmRequestType = setup->bmRequestType; req.ucr_request.bRequest = setup->bRequest; (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) req.ucr_flags = USBD_SHORT_XFER_OK; if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) return _errno_to_libusb(errno); if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) return _errno_to_libusb(errno); itransfer->transferred = req.ucr_actlen; usbi_dbg("transferred %d", itransfer->transferred); return (0); }
int _sync_gen_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer; struct device_priv *dpriv; int fd, nr = 1; transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; if (dpriv->devname == NULL) return (LIBUSB_ERROR_NOT_SUPPORTED); /* * Bulk, Interrupt or Isochronous transfer depends on the * endpoint and thus the node to open. */ if ((fd = _access_endpoint(transfer)) < 0) return _errno_to_libusb(errno); if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) return _errno_to_libusb(errno); if (IS_XFERIN(transfer)) { if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0) return _errno_to_libusb(errno); nr = read(fd, transfer->buffer, transfer->length); } else { nr = write(fd, transfer->buffer, transfer->length); } if (nr < 0) return _errno_to_libusb(errno); itransfer->transferred = nr; return (0); }
int _sync_control_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer; struct libusb_control_setup *setup; struct device_priv *dpriv; struct usb_ctl_request req; transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv; setup = (struct libusb_control_setup *)transfer->buffer; usbi_dbg("type %x request %x value %x index %d length %d timeout %d", setup->bmRequestType, setup->bRequest, libusb_le16_to_cpu(setup->wValue), libusb_le16_to_cpu(setup->wIndex), libusb_le16_to_cpu(setup->wLength), transfer->timeout); req.ucr_addr = transfer->dev_handle->dev->device_address; req.ucr_request.bmRequestType = setup->bmRequestType; req.ucr_request.bRequest = setup->bRequest; /* Don't use USETW, libusb already deals with the endianness */ (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) req.ucr_flags = USBD_SHORT_XFER_OK; if (dpriv->devname == NULL) { /* * XXX If the device is not attached to ugen(4) it is * XXX still possible to submit a control transfer but * XXX with the default timeout only. */ int fd, err; if ((fd = _bus_open(transfer->dev_handle->dev->bus_number)) < 0) return _errno_to_libusb(errno); if ((ioctl(fd, USB_REQUEST, &req)) < 0) { err = errno; close(fd); return _errno_to_libusb(err); } close(fd); } else { if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0) return _errno_to_libusb(errno); if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0) return _errno_to_libusb(errno); } itransfer->transferred = req.ucr_actlen; usbi_dbg("transferred %d", itransfer->transferred); return (0); }
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); } }
static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev); struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); struct winfd wfd; TransferResult transferRes; int i; HANDLE sysHandle; transfer_priv->request.Buffer = (PVOID64)(uintptr_t)transfer->buffer; transfer_priv->request.BufferLength = transfer->length; transfer_priv->request.EndpointAddress = transfer->endpoint; transfer_priv->request.TransferType = IsochronousTransferType; transfer_priv->request.IsochronousPacketsArraySize = transfer->num_iso_packets; transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64)); transfer_priv->request.IsochronousPacketsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousPacketsArray; if (!transfer_priv->IsochronousPacketsArray) { usbi_err(ctx, "Allocation of IsochronousPacketsArray is failed, %s", windows_error_str(0)); return LIBUSB_ERROR_IO; } transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT)); transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)(uintptr_t)transfer_priv->IsochronousResultsArray; if (!transfer_priv->IsochronousResultsArray) { usbi_err(ctx, "Allocation of isochronousResultsArray is failed, %s", windows_error_str(0)); free(transfer_priv->IsochronousPacketsArray); return LIBUSB_ERROR_IO; } for (i = 0; i < transfer->num_iso_packets; i++) transfer_priv->IsochronousPacketsArray[i] = transfer->iso_packet_desc[i].length; transfer_priv->pollable_fd = INVALID_WINFD; sysHandle = usbdk_helper.GetRedirectorSystemHandle(priv->redirector_handle); wfd = usbi_create_fd(sysHandle, IS_XFERIN(transfer) ? RW_READ : RW_WRITE, NULL, NULL); // Always use the handle returned from usbi_create_fd (wfd.handle) if (wfd.fd < 0) { free(transfer_priv->IsochronousPacketsArray); free(transfer_priv->IsochronousResultsArray); return LIBUSB_ERROR_NO_MEM; } if (IS_XFERIN(transfer)) transferRes = usbdk_helper.ReadPipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); else transferRes = usbdk_helper.WritePipe(priv->redirector_handle, &transfer_priv->request, wfd.overlapped); switch (transferRes) { case TransferSuccess: wfd.overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY; break; case TransferSuccessAsync: break; case TransferFailure: usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0)); usbi_free_fd(&wfd); free(transfer_priv->IsochronousPacketsArray); free(transfer_priv->IsochronousResultsArray); return LIBUSB_ERROR_IO; } transfer_priv->pollable_fd = wfd; usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, IS_XFERIN(transfer) ? POLLIN : POLLOUT); return LIBUSB_SUCCESS; }