static void susb_issue_call(struct aura_node *node, struct aura_buffer *buf) { struct aura_object *o = buf->object; struct usb_dev_info *inf = aura_get_transportdata(node); uint8_t rqtype; uint16_t wIndex, wValue, *ptr; size_t datalen; /*Actual data in packet, save for setup */ if (o->retlen) { rqtype = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN; datalen = o->retlen; } else { datalen = o->arglen - 2 * sizeof(uint16_t); rqtype = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT; } ptr = (uint16_t *)&buf->data[buf->pos]; wValue = *ptr++; wIndex = *ptr++; memmove(&buf->data[buf->pos], ptr, datalen); /* * VUSB-based devices (or libusb?) do not seem to play nicely when we have the * setup packet with no data. Transfers may fail instantly. * A typical run at my box gives: * * 9122 succeeded, 878 failed total 10000 * * See tests-transports/test-susb-stability-none * Adding just one byte of data to the packet fix the issue. * Posible workarounds are: * 1. Retry N times * 2. Add just one dummy byte for the transfer * Since nobody reported this workaround breaking support for their * hardware - we'll do it the second way. For now. */ if (!datalen) datalen++; /* buffer's big enough anyway */ /* e.g if device is big endian, but has le descriptors * we have to be extra careful here */ if (node->need_endian_swap) { wValue = __swap16(wValue); wIndex = __swap16(wValue); } inf->current_buffer = buf; libusb_fill_control_setup((unsigned char *)buf->data, rqtype, o->id, wValue, wIndex, datalen); libusb_fill_control_transfer(inf->ctransfer, inf->handle, (unsigned char *)buf->data, cb_call_done, node, 4000); inf->control_retry_count = 0; submit_control(node); }
static void request_object(struct aura_node *node, int id) { struct usb_dev_info *inf = aura_get_transportdata(node); libusb_fill_control_setup(inf->ctrlbuf, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, RQ_GET_OBJ_INFO, 0, id, inf->io_buf_size - LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_transfer(inf->ctransfer, inf->handle, inf->ctrlbuf, cb_parse_object, node, 1500); submit_control(node); }
static void submit_call_write(struct aura_node *node, struct aura_buffer *buf) { struct aura_object *o = buf->object; struct usb_dev_info *inf = aura_get_transportdata(node); slog(4, SLOG_DEBUG, "Writing call %s data to device, %d bytes", o->name, buf->size); inf->current_buffer = buf; libusb_fill_control_setup((unsigned char *)buf->data, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, RQ_PUT_CALL, 0, 0, buf->size - LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_transfer(inf->ctransfer, inf->handle, (unsigned char *) buf->data, cb_call_write_done, node, 1500); submit_control(node); }
static void submit_event_readout(struct aura_node *node) { struct usb_dev_info *inf = aura_get_transportdata(node); struct aura_buffer *buf = aura_buffer_request(node, inf->io_buf_size); if (!buf) return; /* Nothing bad, we'll try again later */ slog(0, SLOG_DEBUG, "Starting evt readout, max %d bytes, pending %d", inf->io_buf_size, inf->pending); libusb_fill_control_setup((unsigned char *)buf->data, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, RQ_GET_EVENT, 0, 0, buf->size - LIBUSB_CONTROL_SETUP_SIZE); libusb_fill_control_transfer(inf->ctransfer, inf->handle, (unsigned char *)buf->data, cb_event_readout_done, node, 1500); inf->current_buffer = buf; submit_control(node); }
static int check_control(struct libusb_transfer *transfer) { struct aura_node *node = transfer->user_data; struct usb_dev_info *inf = aura_get_transportdata(node); int ret = 0; inf->cbusy = false; if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (inf->control_retry_count++ < inf->control_retry_max) { slog(0, SLOG_WARN, "Control transfer failed, retrying (%d/%d)", inf->control_retry_count, inf->control_retry_max); submit_control(inf->node); return -EAGAIN; } slog(0, SLOG_ERROR, "usb: error completing control transfer"); ncusb_print_libusb_transfer(transfer); usb_panic_and_reset_state(node); ret = -EIO; } return ret; }