enum libusb_error uhd_iface_set_protocol(const uhd_iface *iface, bool report, unsigned int timeout) { int rc; assert(uhd_iface_valid(iface)); rc = libusb_control_transfer(iface->dev->handle, /* host->device, class, interface */ 0x21, /* Set_Protocol */ 0x0B, /* 0 - boot, 1 - report */ report ? 1 : 0, /* interface */ iface->number, NULL, 0, timeout); /* * Ignoring EPIPE, which means a STALL handshake, which is OK on * control pipes and indicates request is not supported. * See USB 2.0 spec, 8.4.5 Handshake Packets */ if (rc < 0 && rc != LIBUSB_ERROR_PIPE) return rc; return LIBUSB_SUCCESS; }
enum libusb_error uhd_iface_set_idle(const uhd_iface *iface, uint8_t duration, unsigned int timeout) { int rc; assert(uhd_iface_valid(iface)); rc = libusb_control_transfer(iface->dev->handle, /* host->device, class, interface */ 0x21, /* Set_Idle */ 0x0A, /* duration for all report IDs */ duration << 8, /* interface */ iface->number, NULL, 0, timeout); /* * Ignoring EPIPE, which means a STALL handshake, which is OK on * control pipes and indicates request is not supported. * See USB 2.0 spec, 8.4.5 Handshake Packets */ if (rc < 0 && rc != LIBUSB_ERROR_PIPE) return rc; return LIBUSB_SUCCESS; }
void uhd_iface_free(uhd_iface *iface) { if (iface == NULL) return; assert(uhd_iface_valid(iface)); free(iface); }
static void LIBUSB_CALL dump_iface_list_stream_cb(struct libusb_transfer *transfer) { enum libusb_error err; uhd_iface *iface; assert(transfer != NULL); iface = (uhd_iface *)transfer->user_data; assert(uhd_iface_valid(iface)); /* Clear interface "has transfer submitted" flag */ iface->submitted = false; switch (transfer->status) { case LIBUSB_TRANSFER_COMPLETED: /* Dump the result */ if (!stream_paused) { dump(iface, "STREAM", transfer->buffer, transfer->actual_length); if (stream_feedback) fputc('.', stderr); } /* Resubmit the transfer */ err = libusb_submit_transfer(transfer); if (err != LIBUSB_SUCCESS) LIBUSB_IFACE_FAILURE(iface, "resubmit a transfer"); else { /* Set interface "has transfer submitted" flag */ iface->submitted = true; } break; #define MAP(_name, _desc) \ case LIBUSB_TRANSFER_##_name: \ IFACE_ERROR(iface, _desc); \ break MAP(ERROR, "Interrupt transfer failed"); MAP(TIMED_OUT, "Interrupt transfer timed out"); MAP(STALL, "Interrupt transfer halted (endpoint stalled)"); MAP(NO_DEVICE, "Device was disconnected"); MAP(OVERFLOW, "Interrupt transfer overflowed " "(device sent more data than requested)"); #undef MAP case LIBUSB_TRANSFER_CANCELLED: break; } }
enum libusb_error uhd_iface_clear_halt(uhd_iface *iface) { enum libusb_error err; assert(uhd_iface_valid(iface)); err = libusb_clear_halt(iface->dev->handle, iface->int_in_ep_addr); if (err != LIBUSB_SUCCESS) return err; return LIBUSB_SUCCESS; }
enum libusb_error uhd_iface_detach(uhd_iface *iface) { enum libusb_error err; assert(uhd_iface_valid(iface)); err = libusb_detach_kernel_driver(iface->dev->handle, iface->number); if (err == LIBUSB_SUCCESS) iface->detached = true; else if (err != LIBUSB_ERROR_NOT_FOUND) return err; return LIBUSB_SUCCESS; }
enum libusb_error uhd_iface_release(uhd_iface *iface) { enum libusb_error err; assert(uhd_iface_valid(iface)); err = libusb_release_interface(iface->dev->handle, iface->number); if (err != LIBUSB_SUCCESS) return err; iface->claimed = false; return LIBUSB_SUCCESS; }
enum libusb_error uhd_iface_attach(uhd_iface *iface) { enum libusb_error err; assert(uhd_iface_valid(iface)); if (iface->detached) { err = libusb_attach_kernel_driver(iface->dev->handle, iface->number); if (err != LIBUSB_SUCCESS) return err; iface->detached = false; } return LIBUSB_SUCCESS; }
uhd_iface * uhd_iface_new(const uhd_dev *dev, uint8_t number, uint8_t int_in_ep_addr, uint16_t int_in_ep_maxp) { uhd_iface *iface; libusb_device *lusb_dev; int rc; iface = malloc(sizeof(*iface)); if (iface == NULL) return NULL; iface->next = NULL; iface->dev = dev; iface->number = number; iface->int_in_ep_addr = int_in_ep_addr; iface->int_in_ep_maxp = int_in_ep_maxp; iface->detached = false; iface->claimed = false; iface->submitted = false; /* Format address string */ lusb_dev = libusb_get_device(dev->handle); rc = snprintf(iface->addr_str, sizeof(iface->addr_str), "%.3hhu:%.3hhu:%.3hhu", libusb_get_bus_number(lusb_dev), libusb_get_device_address(lusb_dev), number); assert(rc == (sizeof(iface->addr_str) - 1)); assert(uhd_iface_valid(iface)); return iface; }