static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, int *transferred, unsigned int timeout, unsigned char type) { struct libusb_transfer *transfer = libusb_alloc_transfer(0); int completed = 0; int r; if (!transfer) return LIBUSB_ERROR_NO_MEM; libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, bulk_transfer_cb, &completed, timeout); transfer->type = type; r = libusb_submit_transfer(transfer); if (r < 0) { libusb_free_transfer(transfer); return r; } while (!completed) { r = libusb_handle_events(HANDLE_CTX(dev_handle)); if (r < 0) { libusb_cancel_transfer(transfer); while (!completed) if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0) break; libusb_free_transfer(transfer); return r; } } *transferred = transfer->actual_length; switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: r = 0; break; case LIBUSB_TRANSFER_TIMED_OUT: r = LIBUSB_ERROR_TIMEOUT; break; case LIBUSB_TRANSFER_STALL: r = LIBUSB_ERROR_PIPE; break; case LIBUSB_TRANSFER_OVERFLOW: r = LIBUSB_ERROR_OVERFLOW; break; case LIBUSB_TRANSFER_NO_DEVICE: r = LIBUSB_ERROR_NO_DEVICE; break; default: usbi_warn(HANDLE_CTX(dev_handle), "unrecognised status code %d", transfer->status); r = LIBUSB_ERROR_OTHER; } libusb_free_transfer(transfer); return r; }
int obsd_open(struct libusb_device_handle *handle) { struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; char devnode[16]; if (dpriv->devname) { /* * Only open ugen(4) attached devices read-write, all * read-only operations are done through the bus node. */ snprintf(devnode, sizeof(devnode), DEVPATH "%s.00", dpriv->devname); dpriv->fd = open(devnode, O_RDWR); if (dpriv->fd < 0) return _errno_to_libusb(errno); usbi_dbg("open %s: fd %d", devnode, dpriv->fd); } if (pipe(hpriv->pipe) < 0) return _errno_to_libusb(errno); return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN); }
int API_EXPORTED libusb_get_configuration(libusb_device_handle *dev, int *config) { int r = LIBUSB_ERROR_NOT_SUPPORTED; usbi_dbg(""); if (usbi_backend->get_configuration) r = usbi_backend->get_configuration(dev, config); if (r == LIBUSB_ERROR_NOT_SUPPORTED) { uint8_t tmp = 0; usbi_dbg("falling back to control message"); r = libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, &tmp, 1, 1000); if (r == 0) { usbi_err(HANDLE_CTX(dev), "zero bytes returned in ctrl transfer?"); r = LIBUSB_ERROR_IO; } else if (r == 1) { r = 0; *config = tmp; } else { usbi_dbg("control failed, error %d", r); } } if (r == 0) usbi_dbg("active config %d", *config); return r; }
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); }
void API_EXPORTED libusb_close(libusb_device_handle *dev_handle) { struct libusb_context *ctx; unsigned char dummy = 1; ssize_t r; if (!dev_handle) return; usbi_dbg(""); ctx = HANDLE_CTX(dev_handle); usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify++; usbi_mutex_unlock(&ctx->pollfd_modify_lock); r = usbi_write(ctx->ctrl_pipe[1], &dummy, sizeof(dummy)); if (r <= 0) { usbi_warn(ctx, "internal signalling write failed, closing anyway"); do_close(ctx, dev_handle); usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; usbi_mutex_unlock(&ctx->pollfd_modify_lock); return; } libusb_lock_events(ctx); r = usbi_read(ctx->ctrl_pipe[0], &dummy, sizeof(dummy)); if (r <= 0) usbi_warn(ctx, "internal signalling read failed, closing anyway"); do_close(ctx, dev_handle); usbi_mutex_lock(&ctx->pollfd_modify_lock); ctx->pollfd_modify--; usbi_mutex_unlock(&ctx->pollfd_modify_lock); libusb_unlock_events(ctx); }
void obsd_close(struct libusb_device_handle *handle) { struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; usbi_dbg("close: fd %d", dpriv->fd); close(dpriv->fd); dpriv->fd = -1; usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]); close(hpriv->pipe[0]); close(hpriv->pipe[1]); }
static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) { int r, *completed = transfer->user_data; struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle); while (!*completed) { r = libusb_handle_events_completed(ctx, completed); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying", libusb_error_name(r)); libusb_cancel_transfer(transfer); continue; } } }
int obsd_open(struct libusb_device_handle *handle) { struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; dpriv->fd = open(dpriv->devnode, O_RDWR); if (dpriv->fd < 0) { dpriv->fd = open(dpriv->devnode, O_RDONLY); if (dpriv->fd < 0) return _errno_to_libusb(errno); } usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd); if (pipe(hpriv->pipe) < 0) return _errno_to_libusb(errno); return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN); }
/** \ingroup syncio * Perform a USB control transfer. * * The direction of the transfer is inferred from the bmRequestType field of * the setup packet. * * The wValue, wIndex and wLength fields values should be given in host-endian * byte order. * * \param dev_handle a handle for the device to communicate with * \param bmRequestType the request type field for the setup packet * \param bRequest the request field for the setup packet * \param wValue the value field for the setup packet * \param wIndex the index field for the setup packet * \param data a suitably-sized data buffer for either input or output * (depending on direction bits within bmRequestType) * \param wLength the length field for the setup packet. The data buffer should * be at least this size. * \param timeout timeout (in millseconds) that this function should wait * before giving up due to no response being received. For an unlimited * timeout, use value 0. * \returns on success, the number of bytes actually transferred * \returns LIBUSB_ERROR_TIMEOUT if the transfer timed out * \returns LIBUSB_ERROR_PIPE if the control request was not supported by the * device * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected * \returns another LIBUSB_ERROR code on other failures */ API_EXPORTED int libusb_control_transfer(libusb_device_handle *dev_handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) { struct libusb_transfer *transfer = libusb_alloc_transfer(0); unsigned char *buffer; int completed = 0; int r; if (!transfer) return LIBUSB_ERROR_NO_MEM; buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); if (!buffer) { libusb_free_transfer(transfer); return LIBUSB_ERROR_NO_MEM; } libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength); if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); libusb_fill_control_transfer(transfer, dev_handle, buffer, ctrl_transfer_cb, &completed, timeout); transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; r = libusb_submit_transfer(transfer); if (r < 0) { libusb_free_transfer(transfer); return r; } while (!completed) { r = libusb_handle_events(HANDLE_CTX(dev_handle)); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(transfer); while (!completed) if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0) break; libusb_free_transfer(transfer); return r; } } if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) memcpy(data, libusb_control_transfer_get_data(transfer), transfer->actual_length); switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: r = transfer->actual_length; break; case LIBUSB_TRANSFER_TIMED_OUT: r = LIBUSB_ERROR_TIMEOUT; break; case LIBUSB_TRANSFER_STALL: r = LIBUSB_ERROR_PIPE; break; case LIBUSB_TRANSFER_NO_DEVICE: r = LIBUSB_ERROR_NO_DEVICE; break; default: usbi_warn(HANDLE_CTX(dev_handle), "unrecognised status code %d", transfer->status); r = LIBUSB_ERROR_OTHER; } libusb_free_transfer(transfer); return r; }
static int windows_reset_device(struct libusb_device_handle *dev_handle) { struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); return priv->backend->reset_device(dev_handle); }
static int windows_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) { struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); return priv->backend->clear_halt(dev_handle, endpoint); }
static int windows_set_interface_altsetting(struct libusb_device_handle *dev_handle, int interface_number, int altsetting) { struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); return priv->backend->set_interface_altsetting(dev_handle, interface_number, altsetting); }
static int windows_release_interface(struct libusb_device_handle *dev_handle, int interface_number) { struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); return priv->backend->release_interface(dev_handle, interface_number); }
static int windows_set_configuration(struct libusb_device_handle *dev_handle, int config) { struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); return priv->backend->set_configuration(dev_handle, config); }
static void windows_close(struct libusb_device_handle *dev_handle) { struct windows_context_priv *priv = _context_priv(HANDLE_CTX(dev_handle)); priv->backend->close(dev_handle); }