static void haiku_clear_transfer_priv(struct usbi_transfer * itransfer) { USBTransfer* transfer=*((USBTransfer**)usbi_transfer_get_os_priv(itransfer)); delete transfer; *((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL; }
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 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_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))); }
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 void wince_clear_transfer_priv(struct usbi_transfer *itransfer) { struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd); // No need to cancel transfer as it is either complete or abandoned wfd.itransfer = NULL; CloseHandle(wfd.handle); usbi_free_fd(&transfer_priv->pollable_fd); }
static int wince_handle_events( struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) { struct wince_transfer_priv* transfer_priv = NULL; POLL_NFDS_TYPE i = 0; BOOL found = FALSE; struct usbi_transfer *transfer; DWORD io_size, io_result; int r = LIBUSB_SUCCESS; usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); if (!fds[i].revents) continue; num_ready--; // Because a Windows OVERLAPPED is used for poll emulation, // a pollable fd is created and stored with each transfer usbi_mutex_lock(&ctx->flying_transfers_lock); list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { transfer_priv = usbi_transfer_get_os_priv(transfer); if (transfer_priv->pollable_fd.fd == fds[i].fd) { found = TRUE; break; } } usbi_mutex_unlock(&ctx->flying_transfers_lock); if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) { io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal; io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh; usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd); // let handle_callback free the event using the transfer wfd // If you don't use the transfer wfd, you run a risk of trying to free a // newly allocated wfd that took the place of the one from the transfer. wince_handle_callback(transfer, io_result, io_size); } else if (found) { usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]); r = LIBUSB_ERROR_OTHER; break; } else { usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]); r = LIBUSB_ERROR_NOT_FOUND; break; } } usbi_mutex_unlock(&ctx->open_devs_lock); return r; }
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; }
static int sunos_do_async_io(struct libusb_transfer *transfer) { int ret = -1; struct aiocb *aiocb; sunos_dev_handle_priv_t *hpriv; uint8_t ep; struct sunos_transfer_priv *tpriv; usbi_dbg(""); tpriv = usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer)); hpriv = (sunos_dev_handle_priv_t *)transfer->dev_handle->os_priv; ep = sunos_usb_ep_index(transfer->endpoint); tpriv->transfer = transfer; aiocb = &tpriv->aiocb; bzero(aiocb, sizeof (*aiocb)); aiocb->aio_fildes = hpriv->eps[ep].datafd; aiocb->aio_buf = transfer->buffer; aiocb->aio_nbytes = transfer->length; aiocb->aio_lio_opcode = ((transfer->endpoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) ? LIO_READ:LIO_WRITE; aiocb->aio_sigevent.sigev_notify = SIGEV_THREAD; aiocb->aio_sigevent.sigev_value.sival_ptr = tpriv; aiocb->aio_sigevent.sigev_notify_function = sunos_async_callback; if (aiocb->aio_lio_opcode == LIO_READ) { ret = aio_read(aiocb); } else { ret = aio_write(aiocb); } return (ret); }
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 inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer) { return (struct usbdk_transfer_priv *)usbi_transfer_get_os_priv(itransfer); }