#define USB_TOKEN_IN 0x69 /* device -> host */
#define USB_TOKEN_OUT 0xe1 /* host -> device */
+#define USB_RET_SUCCESS (0)
#define USB_RET_NODEV (-1)
#define USB_RET_NAK (-2)
#define USB_RET_STALL (-3)
* Process control request.
* Called from handle_packet().
*
- * Returns length or one of the USB_RET_ codes.
+ * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
+ * then the number of bytes transfered is stored in p->actual_length
*/
- int (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value,
- int index, int length, uint8_t *data);
+ void (*handle_control)(USBDevice *dev, USBPacket *p, int request, int value,
+ int index, int length, uint8_t *data);
/*
* Process data transfers (both BULK and ISOC).
* Called from handle_packet().
*
- * Returns length or one of the USB_RET_ codes.
+ * Status gets stored in p->status, and if p->status == USB_RET_SUCCESS
+ * then the number of bytes transfered is stored in p->actual_length
*/
- int (*handle_data)(USBDevice *dev, USBPacket *p);
+ void (*handle_data)(USBDevice *dev, USBPacket *p);
void (*set_interface)(USBDevice *dev, int interface,
int alt_old, int alt_new);
uint64_t parameter; /* control transfers */
bool short_not_ok;
bool int_req;
- int result; /* transfer length or USB_RET_* status code */
+ int status; /* USB_RET_* status code */
+ int actual_length; /* Number of bytes actually transfered */
/* Internal use by the USB layer. */
USBPacketState state;
USBCombinedPacket *combined;
USBDevice *usb_find_device(USBPort *port, uint8_t addr);
-int usb_handle_packet(USBDevice *dev, USBPacket *p);
+void usb_handle_packet(USBDevice *dev, USBPacket *p);
void usb_packet_complete(USBDevice *dev, USBPacket *p);
void usb_packet_complete_one(USBDevice *dev, USBPacket *p);
void usb_cancel_packet(USBPacket * p);
void usb_device_handle_reset(USBDevice *dev);
-int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request, int value,
- int index, int length, uint8_t *data);
+void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
+ int val, int index, int length, uint8_t *data);
-int usb_device_handle_data(USBDevice *dev, USBPacket *p);
+void usb_device_handle_data(USBDevice *dev, USBPacket *p);
void usb_device_set_interface(USBDevice *dev, int interface,
int alt_old, int alt_new);
}
}
-int usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
- int value, int index, int length, uint8_t *data)
+void usb_device_handle_control(USBDevice *dev, USBPacket *p, int request,
+ int value, int index, int length, uint8_t *data)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_control) {
- return klass->handle_control(dev, p, request, value, index, length,
- data);
+ klass->handle_control(dev, p, request, value, index, length, data);
}
- return -ENOSYS;
}
-int usb_device_handle_data(USBDevice *dev, USBPacket *p)
+void usb_device_handle_data(USBDevice *dev, USBPacket *p)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->handle_data) {
- return klass->handle_data(dev, p);
+ klass->handle_data(dev, p);
}
- return -ENOSYS;
}
const char *usb_device_get_product_desc(USBDevice *dev)
USBEndpoint *ep = p->ep;
USBPacket *next;
enum { completing, complete, leftover };
- int result, state = completing;
+ int status, actual_length, state = completing;
bool short_not_ok;
if (combined == NULL) {
assert(combined->first == p && p == QTAILQ_FIRST(&combined->packets));
- result = combined->first->result;
+ status = combined->first->status;
+ actual_length = combined->first->actual_length;
short_not_ok = QTAILQ_LAST(&combined->packets, packets_head)->short_not_ok;
QTAILQ_FOREACH_SAFE(p, &combined->packets, combined_entry, next) {
if (state == completing) {
/* Distribute data over uncombined packets */
- if (result >= p->iov.size) {
- p->result = p->iov.size;
+ if (actual_length >= p->iov.size) {
+ p->actual_length = p->iov.size;
} else {
/* Send short or error packet to complete the transfer */
- p->result = result;
+ p->actual_length = actual_length;
state = complete;
}
+ /* Report status on the last packet */
+ if (state == complete || next == NULL) {
+ p->status = status;
+ } else {
+ p->status = USB_RET_SUCCESS;
+ }
p->short_not_ok = short_not_ok;
usb_combined_packet_remove(combined, p);
usb_packet_complete_one(dev, p);
- result -= p->result;
+ actual_length -= p->actual_length;
} else {
/* Remove any leftover packets from the queue */
state = leftover;
- p->result = USB_RET_REMOVE_FROM_QUEUE;
+ p->status = USB_RET_REMOVE_FROM_QUEUE;
dev->port->ops->complete(dev->port, p);
}
}
{
USBPacket *p, *u, *next, *prev = NULL, *first = NULL;
USBPort *port = ep->dev->port;
- int ret, totalsize;
+ int totalsize;
assert(ep->pipeline);
assert(ep->pid == USB_TOKEN_IN);
QTAILQ_FOREACH_SAFE(p, &ep->queue, queue, next) {
/* Empty the queue on a halt */
if (ep->halted) {
- p->result = USB_RET_REMOVE_FROM_QUEUE;
+ p->status = USB_RET_REMOVE_FROM_QUEUE;
port->ops->complete(port, p);
continue;
}
next == NULL ||
/* Work around for Linux usbfs bulk splitting + migration */
(totalsize == 16348 && p->int_req)) {
- ret = usb_device_handle_data(ep->dev, first);
- assert(ret == USB_RET_ASYNC);
+ usb_device_handle_data(ep->dev, first);
+ assert(first->status == USB_RET_ASYNC);
if (first->combined) {
QTAILQ_FOREACH(u, &first->combined->packets, combined_entry) {
usb_packet_set_state(u, USB_PACKET_ASYNC);
#define SETUP_STATE_ACK 3
#define SETUP_STATE_PARAM 4
-static int do_token_setup(USBDevice *s, USBPacket *p)
+static void do_token_setup(USBDevice *s, USBPacket *p)
{
int request, value, index;
- int ret = 0;
if (p->iov.size != 8) {
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ return;
}
usb_packet_copy(p, s->setup_buf, p->iov.size);
- p->result = 0;
+ p->actual_length = 0;
s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
s->setup_index = 0;
index = (s->setup_buf[5] << 8) | s->setup_buf[4];
if (s->setup_buf[0] & USB_DIR_IN) {
- ret = usb_device_handle_control(s, p, request, value, index,
- s->setup_len, s->data_buf);
- if (ret == USB_RET_ASYNC) {
- s->setup_state = SETUP_STATE_SETUP;
- return USB_RET_ASYNC;
+ usb_device_handle_control(s, p, request, value, index,
+ s->setup_len, s->data_buf);
+ if (p->status == USB_RET_ASYNC) {
+ s->setup_state = SETUP_STATE_SETUP;
+ }
+ if (p->status != USB_RET_SUCCESS) {
+ return;
}
- if (ret < 0)
- return ret;
- if (ret < s->setup_len)
- s->setup_len = ret;
+ if (p->actual_length < s->setup_len) {
+ s->setup_len = p->actual_length;
+ }
s->setup_state = SETUP_STATE_DATA;
} else {
if (s->setup_len > sizeof(s->data_buf)) {
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ return;
}
if (s->setup_len == 0)
s->setup_state = SETUP_STATE_ACK;
s->setup_state = SETUP_STATE_DATA;
}
- return ret;
+ p->actual_length = 8;
}
-static int do_token_in(USBDevice *s, USBPacket *p)
+static void do_token_in(USBDevice *s, USBPacket *p)
{
int request, value, index;
- int ret = 0;
assert(p->ep->nr == 0);
switch(s->setup_state) {
case SETUP_STATE_ACK:
if (!(s->setup_buf[0] & USB_DIR_IN)) {
- ret = usb_device_handle_control(s, p, request, value, index,
- s->setup_len, s->data_buf);
- if (ret == USB_RET_ASYNC) {
- return USB_RET_ASYNC;
+ usb_device_handle_control(s, p, request, value, index,
+ s->setup_len, s->data_buf);
+ if (p->status == USB_RET_ASYNC) {
+ return;
}
s->setup_state = SETUP_STATE_IDLE;
- if (ret > 0)
- return 0;
- return ret;
+ p->actual_length = 0;
}
-
- /* return 0 byte */
- return 0;
+ break;
case SETUP_STATE_DATA:
if (s->setup_buf[0] & USB_DIR_IN) {
}
usb_packet_copy(p, s->data_buf + s->setup_index, len);
s->setup_index += len;
- if (s->setup_index >= s->setup_len)
+ if (s->setup_index >= s->setup_len) {
s->setup_state = SETUP_STATE_ACK;
- return len;
+ }
+ return;
}
-
s->setup_state = SETUP_STATE_IDLE;
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ break;
default:
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
}
-static int do_token_out(USBDevice *s, USBPacket *p)
+static void do_token_out(USBDevice *s, USBPacket *p)
{
assert(p->ep->nr == 0);
} else {
/* ignore additional output */
}
- return 0;
+ break;
case SETUP_STATE_DATA:
if (!(s->setup_buf[0] & USB_DIR_IN)) {
}
usb_packet_copy(p, s->data_buf + s->setup_index, len);
s->setup_index += len;
- if (s->setup_index >= s->setup_len)
+ if (s->setup_index >= s->setup_len) {
s->setup_state = SETUP_STATE_ACK;
- return len;
+ }
+ return;
}
-
s->setup_state = SETUP_STATE_IDLE;
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ break;
default:
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
}
-static int do_parameter(USBDevice *s, USBPacket *p)
+static void do_parameter(USBDevice *s, USBPacket *p)
{
- int request, value, index;
- int i, ret = 0;
+ int i, request, value, index;
for (i = 0; i < 8; i++) {
s->setup_buf[i] = p->parameter >> (i*8);
fprintf(stderr,
"usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
s->setup_len, sizeof(s->data_buf));
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ return;
}
if (p->pid == USB_TOKEN_OUT) {
usb_packet_copy(p, s->data_buf, s->setup_len);
}
- ret = usb_device_handle_control(s, p, request, value, index,
- s->setup_len, s->data_buf);
- if (ret < 0) {
- return ret;
+ usb_device_handle_control(s, p, request, value, index,
+ s->setup_len, s->data_buf);
+ if (p->status == USB_RET_ASYNC) {
+ return;
}
- if (ret < s->setup_len) {
- s->setup_len = ret;
+ if (p->actual_length < s->setup_len) {
+ s->setup_len = p->actual_length;
}
if (p->pid == USB_TOKEN_IN) {
+ p->actual_length = 0;
usb_packet_copy(p, s->data_buf, s->setup_len);
}
-
- return ret;
}
/* ctrl complete function for devices which use usb_generic_handle_packet and
usb_packet_complete to complete their async control packets. */
void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
{
- if (p->result < 0) {
+ if (p->status < 0) {
s->setup_state = SETUP_STATE_IDLE;
}
switch (s->setup_state) {
case SETUP_STATE_SETUP:
- if (p->result < s->setup_len) {
- s->setup_len = p->result;
+ if (p->actual_length < s->setup_len) {
+ s->setup_len = p->actual_length;
}
s->setup_state = SETUP_STATE_DATA;
- p->result = 8;
+ p->actual_length = 8;
break;
case SETUP_STATE_ACK:
s->setup_state = SETUP_STATE_IDLE;
- p->result = 0;
+ p->actual_length = 0;
break;
case SETUP_STATE_PARAM:
- if (p->result < s->setup_len) {
- s->setup_len = p->result;
+ if (p->actual_length < s->setup_len) {
+ s->setup_len = p->actual_length;
}
if (p->pid == USB_TOKEN_IN) {
- p->result = 0;
+ p->actual_length = 0;
usb_packet_copy(p, s->data_buf, s->setup_len);
}
break;
return usb_device_find_device(dev, addr);
}
-static int usb_process_one(USBPacket *p)
+static void usb_process_one(USBPacket *p)
{
USBDevice *dev = p->ep->dev;
+ /*
+ * Handlers expect status to be initialized to USB_RET_SUCCESS, but it
+ * can be USB_RET_NAK here from a previous usb_process_one() call,
+ * or USB_RET_ASYNC from going through usb_queue_one().
+ */
+ p->status = USB_RET_SUCCESS;
+
if (p->ep->nr == 0) {
/* control pipe */
if (p->parameter) {
- return do_parameter(dev, p);
+ do_parameter(dev, p);
+ return;
}
switch (p->pid) {
case USB_TOKEN_SETUP:
- return do_token_setup(dev, p);
+ do_token_setup(dev, p);
+ break;
case USB_TOKEN_IN:
- return do_token_in(dev, p);
+ do_token_in(dev, p);
+ break;
case USB_TOKEN_OUT:
- return do_token_out(dev, p);
+ do_token_out(dev, p);
+ break;
default:
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
} else {
/* data pipe */
- return usb_device_handle_data(dev, p);
+ usb_device_handle_data(dev, p);
}
}
-/* Hand over a packet to a device for processing. Return value
+static void usb_queue_one(USBPacket *p)
+{
+ usb_packet_set_state(p, USB_PACKET_QUEUED);
+ QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+ p->status = USB_RET_ASYNC;
+}
+
+/* Hand over a packet to a device for processing. p->status ==
USB_RET_ASYNC indicates the processing isn't finished yet, the
driver will call usb_packet_complete() when done processing it. */
-int usb_handle_packet(USBDevice *dev, USBPacket *p)
+void usb_handle_packet(USBDevice *dev, USBPacket *p)
{
- int ret;
-
if (dev == NULL) {
- return USB_RET_NODEV;
+ p->status = USB_RET_NODEV;
+ return;
}
assert(dev == p->ep->dev);
assert(dev->state == USB_STATE_DEFAULT);
}
if (QTAILQ_EMPTY(&p->ep->queue) || p->ep->pipeline) {
- ret = usb_process_one(p);
- if (ret == USB_RET_ASYNC) {
+ usb_process_one(p);
+ if (p->status == USB_RET_ASYNC) {
assert(p->ep->type != USB_ENDPOINT_XFER_ISOC);
usb_packet_set_state(p, USB_PACKET_ASYNC);
QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
- } else if (ret == USB_RET_ADD_TO_QUEUE) {
- usb_packet_set_state(p, USB_PACKET_QUEUED);
- QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
- ret = USB_RET_ASYNC;
+ } else if (p->status == USB_RET_ADD_TO_QUEUE) {
+ usb_queue_one(p);
} else {
/*
* When pipelining is enabled usb-devices must always return async,
* otherwise packets can complete out of order!
*/
assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue));
- if (ret != USB_RET_NAK) {
- p->result = ret;
+ if (p->status != USB_RET_NAK) {
usb_packet_set_state(p, USB_PACKET_COMPLETE);
}
}
} else {
- ret = USB_RET_ASYNC;
- usb_packet_set_state(p, USB_PACKET_QUEUED);
- QTAILQ_INSERT_TAIL(&p->ep->queue, p, queue);
+ usb_queue_one(p);
}
- return ret;
}
void usb_packet_complete_one(USBDevice *dev, USBPacket *p)
USBEndpoint *ep = p->ep;
assert(QTAILQ_FIRST(&ep->queue) == p);
- assert(p->result != USB_RET_ASYNC && p->result != USB_RET_NAK);
+ assert(p->status != USB_RET_ASYNC && p->status != USB_RET_NAK);
- if (p->result < 0 || (p->short_not_ok && (p->result < p->iov.size))) {
+ if (p->status != USB_RET_SUCCESS ||
+ (p->short_not_ok && (p->actual_length < p->iov.size))) {
ep->halted = true;
}
usb_packet_set_state(p, USB_PACKET_COMPLETE);
void usb_packet_complete(USBDevice *dev, USBPacket *p)
{
USBEndpoint *ep = p->ep;
- int ret;
usb_packet_check_state(p, USB_PACKET_ASYNC);
usb_packet_complete_one(dev, p);
p = QTAILQ_FIRST(&ep->queue);
if (ep->halted) {
/* Empty the queue on a halt */
- p->result = USB_RET_REMOVE_FROM_QUEUE;
+ p->status = USB_RET_REMOVE_FROM_QUEUE;
dev->port->ops->complete(dev->port, p);
continue;
}
break;
}
usb_packet_check_state(p, USB_PACKET_QUEUED);
- ret = usb_process_one(p);
- if (ret == USB_RET_ASYNC) {
+ usb_process_one(p);
+ if (p->status == USB_RET_ASYNC) {
usb_packet_set_state(p, USB_PACKET_ASYNC);
break;
}
- p->result = ret;
usb_packet_complete_one(ep->dev, p);
}
}
p->id = id;
p->pid = pid;
p->ep = ep;
- p->result = 0;
+ p->status = USB_RET_SUCCESS;
+ p->actual_length = 0;
p->parameter = 0;
p->short_not_ok = short_not_ok;
p->int_req = int_req;
void usb_packet_copy(USBPacket *p, void *ptr, size_t bytes)
{
- assert(p->result >= 0);
- assert(p->result + bytes <= p->iov.size);
+ assert(p->actual_length >= 0);
+ assert(p->actual_length + bytes <= p->iov.size);
switch (p->pid) {
case USB_TOKEN_SETUP:
case USB_TOKEN_OUT:
- iov_to_buf(p->iov.iov, p->iov.niov, p->result, ptr, bytes);
+ iov_to_buf(p->iov.iov, p->iov.niov, p->actual_length, ptr, bytes);
break;
case USB_TOKEN_IN:
- iov_from_buf(p->iov.iov, p->iov.niov, p->result, ptr, bytes);
+ iov_from_buf(p->iov.iov, p->iov.niov, p->actual_length, ptr, bytes);
break;
default:
fprintf(stderr, "%s: invalid pid: %x\n", __func__, p->pid);
abort();
}
- p->result += bytes;
+ p->actual_length += bytes;
}
void usb_packet_skip(USBPacket *p, size_t bytes)
{
- assert(p->result >= 0);
- assert(p->result + bytes <= p->iov.size);
+ assert(p->actual_length >= 0);
+ assert(p->actual_length + bytes <= p->iov.size);
if (p->pid == USB_TOKEN_IN) {
- iov_memset(p->iov.iov, p->iov.niov, p->result, 0, bytes);
+ iov_memset(p->iov.iov, p->iov.niov, p->actual_length, 0, bytes);
}
- p->result += bytes;
+ p->actual_length += bytes;
}
void usb_packet_cleanup(USBPacket *p)
return pos;
}
-int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
+int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
+ int value, uint8_t *dest, size_t len)
{
const USBDesc *desc = usb_device_get_usb_desc(dev);
const USBDescDevice *other_dev;
ret = len;
}
memcpy(dest, buf, ret);
+ p->actual_length = ret;
+ ret = 0;
}
return ret;
}
break;
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- ret = usb_desc_get_descriptor(dev, value, data, length);
+ ret = usb_desc_get_descriptor(dev, p, value, data, length);
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
* the non zero value of bConfigurationValue.
*/
data[0] = dev->config ? dev->config->bConfigurationValue : 0;
- ret = 1;
+ p->actual_length = 1;
+ ret = 0;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = usb_desc_set_config(dev, value);
data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
}
data[1] = 0x00;
- ret = 2;
+ p->actual_length = 2;
+ ret = 0;
break;
}
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
break;
}
data[0] = dev->altsetting[index];
- ret = 1;
+ p->actual_length = 1;
+ ret = 0;
break;
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
ret = usb_desc_set_interface(dev, index, value);
void usb_desc_create_serial(USBDevice *dev);
const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
-int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
+int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
+ int value, uint8_t *dest, size_t len);
int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data);
return ret;
}
-static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_audio_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index,
int length, uint8_t *data)
{
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
switch (request) {
}
goto fail;
}
+ p->actual_length = ret;
break;
case ClassInterfaceOutRequest | CR_SET_CUR:
"request 0x%04x value 0x%04x index 0x%04x length 0x%04x\n",
request, value, index, length);
}
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
static void usb_audio_set_interface(USBDevice *dev, int iface,
usb_audio_set_output_altset(s, ALTSET_OFF);
}
-static int usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
+static void usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
{
- int rc;
-
if (s->out.altset == ALTSET_OFF) {
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ return;
}
- rc = streambuf_put(&s->out.buf, p);
- if (rc < p->iov.size && s->debug > 1) {
+ streambuf_put(&s->out.buf, p);
+ if (p->actual_length < p->iov.size && s->debug > 1) {
fprintf(stderr, "usb-audio: output overrun (%zd bytes)\n",
- p->iov.size - rc);
+ p->iov.size - p->actual_length);
}
-
- return 0;
}
-static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_audio_handle_data(USBDevice *dev, USBPacket *p)
{
USBAudioState *s = (USBAudioState *) dev;
- int ret = 0;
- switch (p->pid) {
- case USB_TOKEN_OUT:
- switch (p->ep->nr) {
- case 1:
- ret = usb_audio_handle_dataout(s, p);
- break;
- default:
- goto fail;
- }
- break;
-
- default:
-fail:
- ret = USB_RET_STALL;
- break;
+ if (p->pid == USB_TOKEN_OUT && p->ep->nr == 1) {
+ usb_audio_handle_dataout(s, p);
+ return;
}
- if (ret == USB_RET_STALL && s->debug) {
+
+ p->status = USB_RET_STALL;
+ if (s->debug) {
fprintf(stderr, "usb-audio: failed data transaction: "
"pid 0x%x ep 0x%x len 0x%zx\n",
p->pid, p->ep->nr, p->iov.size);
}
- return ret;
}
static void usb_audio_handle_destroy(USBDevice *dev)
fifo->fifo[off].len = len;
}
-static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
+static inline void usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
USBPacket *p)
{
int len;
- if (likely(!fifo->len))
- return USB_RET_STALL;
+ if (likely(!fifo->len)) {
+ p->status = USB_RET_STALL;
+ return;
+ }
len = MIN(p->iov.size, fifo->fifo[fifo->start].len);
usb_packet_copy(p, fifo->fifo[fifo->start].data, len);
fifo->dstart = 0;
fifo->dsize = DFIFO_LEN_MASK + 1;
}
-
- return len;
}
static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
s->outsco.len = 0;
}
-static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_bt_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
struct USBBtState *s = (struct USBBtState *) dev->opaque;
usb_bt_fifo_reset(&s->sco);
break;
}
- return ret;
+ return;
}
- ret = 0;
switch (request) {
case InterfaceRequest | USB_REQ_GET_STATUS:
case EndpointRequest | USB_REQ_GET_STATUS:
data[0] = 0x00;
data[1] = 0x00;
- ret = 2;
+ p->actual_length = 2;
break;
case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE:
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
break;
default:
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
-static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_bt_handle_data(USBDevice *dev, USBPacket *p)
{
struct USBBtState *s = (struct USBBtState *) dev->opaque;
- int ret = 0;
if (!s->config)
goto fail;
case USB_TOKEN_IN:
switch (p->ep->nr) {
case USB_EVT_EP:
- ret = usb_bt_fifo_dequeue(&s->evt, p);
+ usb_bt_fifo_dequeue(&s->evt, p);
break;
case USB_ACL_EP:
- ret = usb_bt_fifo_dequeue(&s->acl, p);
+ usb_bt_fifo_dequeue(&s->acl, p);
break;
case USB_SCO_EP:
- ret = usb_bt_fifo_dequeue(&s->sco, p);
+ usb_bt_fifo_dequeue(&s->sco, p);
break;
default:
default:
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
-
- return ret;
}
static void usb_bt_out_hci_packet_event(void *opaque,
hid_reset(&us->hid);
}
-static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
- ret = 0;
switch (request) {
/* hid specific requests */
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
if (hs->kind == HID_MOUSE) {
memcpy(data, qemu_mouse_hid_report_descriptor,
sizeof(qemu_mouse_hid_report_descriptor));
- ret = sizeof(qemu_mouse_hid_report_descriptor);
+ p->actual_length = sizeof(qemu_mouse_hid_report_descriptor);
} else if (hs->kind == HID_TABLET) {
memcpy(data, qemu_tablet_hid_report_descriptor,
sizeof(qemu_tablet_hid_report_descriptor));
- ret = sizeof(qemu_tablet_hid_report_descriptor);
+ p->actual_length = sizeof(qemu_tablet_hid_report_descriptor);
} else if (hs->kind == HID_KEYBOARD) {
memcpy(data, qemu_keyboard_hid_report_descriptor,
sizeof(qemu_keyboard_hid_report_descriptor));
- ret = sizeof(qemu_keyboard_hid_report_descriptor);
+ p->actual_length = sizeof(qemu_keyboard_hid_report_descriptor);
}
break;
default:
break;
case GET_REPORT:
if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
- ret = hid_pointer_poll(hs, data, length);
+ p->actual_length = hid_pointer_poll(hs, data, length);
} else if (hs->kind == HID_KEYBOARD) {
- ret = hid_keyboard_poll(hs, data, length);
+ p->actual_length = hid_keyboard_poll(hs, data, length);
}
break;
case SET_REPORT:
if (hs->kind == HID_KEYBOARD) {
- ret = hid_keyboard_write(hs, data, length);
+ p->actual_length = hid_keyboard_write(hs, data, length);
} else {
goto fail;
}
if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
goto fail;
}
- ret = 1;
data[0] = hs->protocol;
+ p->actual_length = 1;
break;
case SET_PROTOCOL:
if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
goto fail;
}
- ret = 0;
hs->protocol = value;
break;
case GET_IDLE:
- ret = 1;
data[0] = hs->idle;
+ p->actual_length = 1;
break;
case SET_IDLE:
hs->idle = (uint8_t) (value >> 8);
if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
hid_pointer_activate(hs);
}
- ret = 0;
break;
default:
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
-static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
{
USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
HIDState *hs = &us->hid;
uint8_t buf[p->iov.size];
- int ret = 0;
+ int len = 0;
switch (p->pid) {
case USB_TOKEN_IN:
}
if (!hid_has_events(hs) &&
(!hs->idle || hs->next_idle_clock - curtime > 0)) {
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
+ return;
}
hid_set_next_idle(hs, curtime);
if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
- ret = hid_pointer_poll(hs, buf, p->iov.size);
+ len = hid_pointer_poll(hs, buf, p->iov.size);
} else if (hs->kind == HID_KEYBOARD) {
- ret = hid_keyboard_poll(hs, buf, p->iov.size);
+ len = hid_keyboard_poll(hs, buf, p->iov.size);
}
- usb_packet_copy(p, buf, ret);
+ usb_packet_copy(p, buf, len);
} else {
goto fail;
}
case USB_TOKEN_OUT:
default:
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
static void usb_hid_handle_destroy(USBDevice *dev)
return name[feature] ?: "?";
}
-static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_hub_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
USBHubState *s = (USBHubState *)dev;
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
switch(request) {
if (value == 0 && index != 0x81) { /* clear ep halt */
goto fail;
}
- ret = 0;
break;
/* usb specific requests */
case GetHubStatus:
data[1] = 0;
data[2] = 0;
data[3] = 0;
- ret = 4;
+ p->actual_length = 4;
break;
case GetPortStatus:
{
data[1] = port->wPortStatus >> 8;
data[2] = port->wPortChange;
data[3] = port->wPortChange >> 8;
- ret = 4;
+ p->actual_length = 4;
}
break;
case SetHubFeature:
case ClearHubFeature:
- if (value == 0 || value == 1) {
- } else {
+ if (value != 0 && value != 1) {
goto fail;
}
- ret = 0;
break;
case SetPortFeature:
{
default:
goto fail;
}
- ret = 0;
}
break;
case ClearPortFeature:
default:
goto fail;
}
- ret = 0;
}
break;
case GetHubDescriptor:
var_hub_size++;
}
- ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
- data[0] = ret;
+ p->actual_length = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
+ data[0] = p->actual_length;
break;
}
default:
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
-static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_hub_handle_data(USBDevice *dev, USBPacket *p)
{
USBHubState *s = (USBHubState *)dev;
- int ret;
switch(p->pid) {
case USB_TOKEN_IN:
if (p->iov.size == 1) { /* FreeBSD workaround */
n = 1;
} else if (n > p->iov.size) {
- return USB_RET_BABBLE;
+ p->status = USB_RET_BABBLE;
+ return;
}
status = 0;
for(i = 0; i < NUM_PORTS; i++) {
buf[i] = status >> (8 * i);
}
usb_packet_copy(p, buf, n);
- ret = n;
} else {
- ret = USB_RET_NAK; /* usb11 11.13.1 */
+ p->status = USB_RET_NAK; /* usb11 11.13.1 */
}
} else {
goto fail;
case USB_TOKEN_OUT:
default:
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
static void usb_hub_handle_destroy(USBDevice *dev)
{
}
-static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_net_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
USBNetState *s = (USBNetState *) dev;
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
- ret = 0;
switch(request) {
case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
if (!is_rndis(s) || value || index != 0) {
}
#endif
ret = rndis_parse(s, data, length);
+ if (ret < 0) {
+ p->status = ret;
+ }
break;
case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
if (!is_rndis(s) || value || index != 0) {
goto fail;
}
- ret = rndis_get_response(s, data);
- if (!ret) {
+ p->actual_length = rndis_get_response(s, data);
+ if (p->actual_length == 0) {
data[0] = 0;
- ret = 1;
+ p->actual_length = 1;
}
#ifdef TRAFFIC_DEBUG
{
unsigned int i;
fprintf(stderr, "GET_ENCAPSULATED_RESPONSE:");
- for (i = 0; i < ret; i++) {
+ for (i = 0; i < p->actual_length; i++) {
if (!(i & 15))
fprintf(stderr, "\n%04x:", i);
fprintf(stderr, " %02x", data[i]);
fprintf(stderr, "usbnet: failed control transaction: "
"request 0x%x value 0x%x index 0x%x length 0x%x\n",
request, value, index, length);
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
-static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
+static void usb_net_handle_statusin(USBNetState *s, USBPacket *p)
{
le32 buf[2];
- int ret = 8;
if (p->iov.size < 8) {
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ return;
}
buf[0] = cpu_to_le32(1);
buf[1] = cpu_to_le32(0);
usb_packet_copy(p, buf, 8);
- if (!s->rndis_resp.tqh_first)
- ret = USB_RET_NAK;
+ if (!s->rndis_resp.tqh_first) {
+ p->status = USB_RET_NAK;
+ }
#ifdef TRAFFIC_DEBUG
fprintf(stderr, "usbnet: interrupt poll len %zu return %d",
- p->iov.size, ret);
- iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
+ p->iov.size, p->status);
+ iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", p->status);
#endif
-
- return ret;
}
-static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
+static void usb_net_handle_datain(USBNetState *s, USBPacket *p)
{
- int ret = USB_RET_NAK;
+ int len;
if (s->in_ptr > s->in_len) {
usb_net_reset_in_buf(s);
- ret = USB_RET_NAK;
- return ret;
+ p->status = USB_RET_NAK;
+ return;
}
if (!s->in_len) {
- ret = USB_RET_NAK;
- return ret;
+ p->status = USB_RET_NAK;
+ return;
}
- ret = s->in_len - s->in_ptr;
- if (ret > p->iov.size) {
- ret = p->iov.size;
+ len = s->in_len - s->in_ptr;
+ if (len > p->iov.size) {
+ len = p->iov.size;
}
- usb_packet_copy(p, &s->in_buf[s->in_ptr], ret);
- s->in_ptr += ret;
+ usb_packet_copy(p, &s->in_buf[s->in_ptr], len);
+ s->in_ptr += len;
if (s->in_ptr >= s->in_len &&
- (is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) {
+ (is_rndis(s) || (s->in_len & (64 - 1)) || !len)) {
/* no short packet necessary */
usb_net_reset_in_buf(s);
}
#ifdef TRAFFIC_DEBUG
- fprintf(stderr, "usbnet: data in len %zu return %d", p->iov.size, ret);
- iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", ret);
+ fprintf(stderr, "usbnet: data in len %zu return %d", p->iov.size, len);
+ iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", len);
#endif
-
- return ret;
}
-static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
+static void usb_net_handle_dataout(USBNetState *s, USBPacket *p)
{
- int ret = p->iov.size;
int sz = sizeof(s->out_buf) - s->out_ptr;
struct rndis_packet_msg_type *msg =
(struct rndis_packet_msg_type *) s->out_buf;
iov_hexdump(p->iov.iov, p->iov.niov, stderr, "usbnet", p->iov.size);
#endif
- if (sz > ret)
- sz = ret;
+ if (sz > p->iov.size) {
+ sz = p->iov.size;
+ }
usb_packet_copy(p, &s->out_buf[s->out_ptr], sz);
s->out_ptr += sz;
if (!is_rndis(s)) {
- if (ret < 64) {
+ if (p->iov.size < 64) {
qemu_send_packet(&s->nic->nc, s->out_buf, s->out_ptr);
s->out_ptr = 0;
}
- return ret;
+ return;
}
len = le32_to_cpu(msg->MessageLength);
- if (s->out_ptr < 8 || s->out_ptr < len)
- return ret;
+ if (s->out_ptr < 8 || s->out_ptr < len) {
+ return;
+ }
if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
uint32_t size = le32_to_cpu(msg->DataLength);
}
s->out_ptr -= len;
memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
-
- return ret;
}
-static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_net_handle_data(USBDevice *dev, USBPacket *p)
{
USBNetState *s = (USBNetState *) dev;
- int ret = 0;
switch(p->pid) {
case USB_TOKEN_IN:
switch (p->ep->nr) {
case 1:
- ret = usb_net_handle_statusin(s, p);
+ usb_net_handle_statusin(s, p);
break;
case 2:
- ret = usb_net_handle_datain(s, p);
+ usb_net_handle_datain(s, p);
break;
default:
case USB_TOKEN_OUT:
switch (p->ep->nr) {
case 2:
- ret = usb_net_handle_dataout(s, p);
+ usb_net_handle_dataout(s, p);
break;
default:
default:
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- if (ret == USB_RET_STALL)
+
+ if (p->status == USB_RET_STALL) {
fprintf(stderr, "usbnet: failed data transaction: "
"pid 0x%x ep 0x%x len 0x%zx\n",
p->pid, p->ep->nr, p->iov.size);
- return ret;
+ }
}
static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t size)
return ret;
}
-static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
USBSerialState *s = (USBSerialState *)dev;
DPRINTF("got control %x, value %x\n",request, value);
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
- ret = 0;
switch (request) {
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
- ret = 0;
break;
/* Class specific requests. */
case DeviceInVendor | FTDI_GET_MDM_ST:
data[0] = usb_get_modem_lines(s) | 1;
data[1] = 0;
- ret = 2;
+ p->actual_length = 2;
break;
case DeviceOutVendor | FTDI_SET_EVENT_CHR:
/* TODO: handle it */
break;
case DeviceInVendor | FTDI_GET_LATENCY:
data[0] = s->latency;
- ret = 1;
+ p->actual_length = 1;
break;
default:
fail:
DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
-static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_serial_handle_data(USBDevice *dev, USBPacket *p)
{
USBSerialState *s = (USBSerialState *)dev;
- int i, ret = 0;
uint8_t devep = p->ep->nr;
struct iovec *iov;
uint8_t header[2];
- int first_len, len;
+ int i, first_len, len;
switch (p->pid) {
case USB_TOKEN_OUT:
iov = p->iov.iov + i;
qemu_chr_fe_write(s->cs, iov->iov_base, iov->iov_len);
}
+ p->actual_length = p->iov.size;
break;
case USB_TOKEN_IN:
first_len = RECV_BUF - s->recv_ptr;
len = p->iov.size;
if (len <= 2) {
- ret = USB_RET_NAK;
+ p->status = USB_RET_NAK;
break;
}
header[0] = usb_get_modem_lines(s) | 1;
s->event_trigger &= ~FTDI_BI;
header[1] = FTDI_BI;
usb_packet_copy(p, header, 2);
- ret = 2;
break;
} else {
header[1] = 0;
if (len > s->recv_used)
len = s->recv_used;
if (!len) {
- ret = USB_RET_NAK;
+ p->status = USB_RET_NAK;
break;
}
if (first_len > len)
usb_packet_copy(p, s->recv_buf, len - first_len);
s->recv_used -= len;
s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
- ret = len + 2;
break;
default:
DPRINTF("Bad token\n");
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
-
- return ret;
}
static void usb_serial_handle_destroy(USBDevice *dev)
ccid_reset(s);
}
-static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
+static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
int value, int index, int length, uint8_t *data)
{
USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
- int ret = 0;
+ int ret;
DPRINTF(s, 1, "got control %x, value %x\n", request, value);
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
switch (request) {
/* Class specific requests. */
case InterfaceOutClass | CCID_CONTROL_ABORT:
DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
default:
DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
request, value);
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
static bool ccid_card_inserted(USBCCIDState *s)
}
}
-/*
- * Handle a single USB_TOKEN_OUT, return value returned to guest.
- * Return value:
- * 0 - all ok
- * USB_RET_STALL - failed to handle packet
- */
-static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
{
CCID_Header *ccid_header;
if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ return;
}
ccid_header = (CCID_Header *)s->bulk_out_data;
usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
DPRINTF(s, D_VERBOSE,
"usb-ccid: bulk_in: expecting more packets (%zd/%d)\n",
p->iov.size, ccid_header->dwLength);
- return 0;
+ return;
}
if (s->bulk_out_pos < 10) {
DPRINTF(s, 1,
}
}
s->bulk_out_pos = 0;
- return 0;
}
-static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
+static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
{
- int ret = 0;
+ int len = 0;
- assert(p->iov.size > 0);
ccid_bulk_in_get(s);
if (s->current_bulk_in != NULL) {
- ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
+ len = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
p->iov.size);
usb_packet_copy(p, s->current_bulk_in->data +
- s->current_bulk_in->pos, ret);
- s->current_bulk_in->pos += ret;
+ s->current_bulk_in->pos, len);
+ s->current_bulk_in->pos += len;
if (s->current_bulk_in->pos == s->current_bulk_in->len) {
ccid_bulk_in_release(s);
}
} else {
/* return when device has no data - usb 2.0 spec Table 8-4 */
- ret = USB_RET_NAK;
+ p->status = USB_RET_NAK;
}
- if (ret > 0) {
+ if (len) {
DPRINTF(s, D_MORE_INFO,
"%s: %zd/%d req/act to guest (BULK_IN)\n",
- __func__, p->iov.size, ret);
+ __func__, p->iov.size, len);
}
- if (ret != USB_RET_NAK && ret < p->iov.size) {
+ if (len < p->iov.size) {
DPRINTF(s, 1,
"%s: returning short (EREMOTEIO) %d < %zd\n",
- __func__, ret, p->iov.size);
+ __func__, len, p->iov.size);
}
- return ret;
}
-static int ccid_handle_data(USBDevice *dev, USBPacket *p)
+static void ccid_handle_data(USBDevice *dev, USBPacket *p)
{
USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
- int ret = 0;
uint8_t buf[2];
switch (p->pid) {
case USB_TOKEN_OUT:
- ret = ccid_handle_bulk_out(s, p);
+ ccid_handle_bulk_out(s, p);
break;
case USB_TOKEN_IN:
switch (p->ep->nr) {
case CCID_BULK_IN_EP:
- if (!p->iov.size) {
- ret = USB_RET_NAK;
- } else {
- ret = ccid_bulk_in_copy_to_guest(s, p);
- }
+ ccid_bulk_in_copy_to_guest(s, p);
break;
case CCID_INT_IN_EP:
if (s->notify_slot_change) {
buf[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
buf[1] = s->bmSlotICCState;
usb_packet_copy(p, buf, 2);
- ret = 2;
s->notify_slot_change = false;
s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK;
DPRINTF(s, D_INFO,
break;
default:
DPRINTF(s, 1, "Bad endpoint\n");
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
break;
default:
DPRINTF(s, 1, "Bad token\n");
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
-
- return ret;
}
static void ccid_handle_destroy(USBDevice *dev)
static void usb_msd_copy_data(MSDState *s, USBPacket *p)
{
uint32_t len;
- len = p->iov.size - p->result;
+ len = p->iov.size - p->actual_length;
if (len > s->scsi_len)
len = s->scsi_len;
usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
if (p) {
usb_msd_copy_data(s, p);
p = s->packet;
- if (p && p->result == p->iov.size) {
+ if (p && p->actual_length == p->iov.size) {
+ p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
usb_msd_packet_complete(s);
}
}
s->mode = USB_MSDM_CBW;
} else {
if (s->data_len) {
- int len = (p->iov.size - p->result);
+ int len = (p->iov.size - p->actual_length);
usb_packet_skip(p, len);
s->data_len -= len;
}
s->mode = USB_MSDM_CSW;
}
}
+ p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
usb_msd_packet_complete(s);
} else if (s->data_len == 0) {
s->mode = USB_MSDM_CSW;
assert(s->req == NULL);
if (s->packet) {
- s->packet->result = USB_RET_STALL;
+ s->packet->status = USB_RET_STALL;
usb_msd_packet_complete(s);
}
s->mode = USB_MSDM_CBW;
}
-static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_msd_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
MSDState *s = (MSDState *)dev;
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
- ret = 0;
switch (request) {
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
- ret = 0;
break;
/* Class specific requests. */
case ClassInterfaceOutRequest | MassStorageReset:
/* Reset state ready for the next CBW. */
s->mode = USB_MSDM_CBW;
- ret = 0;
break;
case ClassInterfaceRequest | GetMaxLun:
data[0] = 0;
- ret = 1;
+ p->actual_length = 1;
break;
default:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
}
}
-static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
{
MSDState *s = (MSDState *)dev;
uint32_t tag;
- int ret = 0;
struct usb_msd_cbw cbw;
uint8_t devep = p->ep->nr;
if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
scsi_req_continue(s->req);
}
- ret = p->result;
break;
case USB_MSDM_DATAOUT:
usb_msd_copy_data(s, p);
}
if (le32_to_cpu(s->csw.residue)) {
- int len = p->iov.size - p->result;
+ int len = p->iov.size - p->actual_length;
if (len) {
usb_packet_skip(p, len);
s->data_len -= len;
}
}
}
- if (p->result < p->iov.size) {
+ if (p->actual_length < p->iov.size) {
DPRINTF("Deferring packet %p [wait data-out]\n", p);
s->packet = p;
- ret = USB_RET_ASYNC;
- } else {
- ret = p->result;
+ p->status = USB_RET_ASYNC;
}
break;
}
/* Waiting for SCSI write to complete. */
s->packet = p;
- ret = USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
break;
case USB_MSDM_CSW:
/* still in flight */
DPRINTF("Deferring packet %p [wait status]\n", p);
s->packet = p;
- ret = USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
} else {
usb_msd_send_status(s, p);
s->mode = USB_MSDM_CBW;
- ret = 13;
}
break;
usb_msd_copy_data(s, p);
}
if (le32_to_cpu(s->csw.residue)) {
- int len = p->iov.size - p->result;
+ int len = p->iov.size - p->actual_length;
if (len) {
usb_packet_skip(p, len);
s->data_len -= len;
}
}
}
- if (p->result < p->iov.size) {
+ if (p->actual_length < p->iov.size) {
DPRINTF("Deferring packet %p [wait data-in]\n", p);
s->packet = p;
- ret = USB_RET_ASYNC;
- } else {
- ret = p->result;
+ p->status = USB_RET_ASYNC;
}
break;
default:
DPRINTF("Bad token\n");
fail:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
-
- return ret;
}
static void usb_msd_password_cb(void *opaque, int err)
uas->status = NULL;
usb_packet_copy(p, &st->status, st->length);
- p->result = st->length;
QTAILQ_REMOVE(&uas->results, st, next);
g_free(st);
+ p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
usb_packet_complete(&uas->dev, p);
}
p = req->data;
req->data = NULL;
req->data_async = false;
+ p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
usb_packet_complete(&req->uas->dev, p);
}
uint32_t length;
length = MIN(req->buf_size - req->buf_off,
- req->data->iov.size - req->data->result);
+ req->data->iov.size - req->data->actual_length);
trace_usb_uas_xfer_data(req->uas->dev.addr, req->tag, length,
- req->data->result, req->data->iov.size,
+ req->data->actual_length, req->data->iov.size,
req->buf_off, req->buf_size);
usb_packet_copy(req->data, scsi_req_get_buf(req->req) + req->buf_off,
length);
req->buf_off += length;
req->data_off += length;
- if (req->data->result == req->data->iov.size) {
+ if (req->data->actual_length == req->data->iov.size) {
usb_uas_complete_data_packet(req);
}
if (req->buf_size && req->buf_off == req->buf_size) {
}
}
-static int usb_uas_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_uas_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
int ret;
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
fprintf(stderr, "%s: unhandled control request\n", __func__);
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p)
usb_uas_queue_response(uas, tag, UAS_RC_INCORRECT_LUN, 0);
}
-static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
{
UASDevice *uas = DO_UPCAST(UASDevice, dev, dev);
uas_ui ui;
UASStatus *st;
UASRequest *req;
- int length, ret = 0;
+ int length;
switch (p->ep->nr) {
case UAS_PIPE_ID_COMMAND:
switch (ui.hdr.id) {
case UAS_UI_COMMAND:
usb_uas_command(uas, &ui);
- ret = length;
break;
case UAS_UI_TASK_MGMT:
usb_uas_task(uas, &ui);
- ret = length;
break;
default:
fprintf(stderr, "%s: unknown command ui: id 0x%x\n",
__func__, ui.hdr.id);
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
break;
if (st == NULL) {
assert(uas->status == NULL);
uas->status = p;
- ret = USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
break;
}
usb_packet_copy(p, &st->status, st->length);
- ret = st->length;
QTAILQ_REMOVE(&uas->results, st, next);
g_free(st);
break;
req = (p->ep->nr == UAS_PIPE_ID_DATA_IN) ? uas->datain : uas->dataout;
if (req == NULL) {
fprintf(stderr, "%s: no inflight request\n", __func__);
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
scsi_req_ref(req->req);
req->data = p;
usb_uas_copy_data(req);
- if (p->result == p->iov.size || req->complete) {
+ if (p->actual_length == p->iov.size || req->complete) {
req->data = NULL;
- ret = p->result;
} else {
req->data_async = true;
- ret = USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
scsi_req_unref(req->req);
usb_uas_start_next_transfer(uas);
break;
default:
fprintf(stderr, "%s: invalid endpoint %d\n", __func__, p->ep->nr);
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
static void usb_uas_handle_destroy(USBDevice *dev)
s->mode = WACOM_MODE_HID;
}
-static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
USBWacomState *s = (USBWacomState *) dev;
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
if (ret >= 0) {
- return ret;
+ return;
}
- ret = 0;
switch (request) {
case WACOM_SET_REPORT:
if (s->mouse_grabbed) {
s->mouse_grabbed = 0;
}
s->mode = data[0];
- ret = 0;
break;
case WACOM_GET_REPORT:
data[0] = 0;
data[1] = s->mode;
- ret = 2;
+ p->actual_length = 2;
break;
/* USB HID requests */
case HID_GET_REPORT:
if (s->mode == WACOM_MODE_HID)
- ret = usb_mouse_poll(s, data, length);
+ p->actual_length = usb_mouse_poll(s, data, length);
else if (s->mode == WACOM_MODE_WACOM)
- ret = usb_wacom_poll(s, data, length);
+ p->actual_length = usb_wacom_poll(s, data, length);
break;
case HID_GET_IDLE:
- ret = 1;
data[0] = s->idle;
+ p->actual_length = 1;
break;
case HID_SET_IDLE:
s->idle = (uint8_t) (value >> 8);
- ret = 0;
break;
default:
- ret = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
}
- return ret;
}
-static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
{
USBWacomState *s = (USBWacomState *) dev;
uint8_t buf[p->iov.size];
- int ret = 0;
+ int len = 0;
switch (p->pid) {
case USB_TOKEN_IN:
if (p->ep->nr == 1) {
- if (!(s->changed || s->idle))
- return USB_RET_NAK;
+ if (!(s->changed || s->idle)) {
+ p->status = USB_RET_NAK;
+ return;
+ }
s->changed = 0;
if (s->mode == WACOM_MODE_HID)
- ret = usb_mouse_poll(s, buf, p->iov.size);
+ len = usb_mouse_poll(s, buf, p->iov.size);
else if (s->mode == WACOM_MODE_WACOM)
- ret = usb_wacom_poll(s, buf, p->iov.size);
- usb_packet_copy(p, buf, ret);
+ len = usb_wacom_poll(s, buf, p->iov.size);
+ usb_packet_copy(p, buf, len);
break;
}
/* Fall through. */
case USB_TOKEN_OUT:
default:
- ret = USB_RET_STALL;
- break;
+ p->status = USB_RET_STALL;
}
- return ret;
}
static void usb_wacom_handle_destroy(USBDevice *dev)
p = container_of(packet, EHCIPacket, packet);
assert(p->async == EHCI_ASYNC_INFLIGHT);
- if (packet->result == USB_RET_REMOVE_FROM_QUEUE) {
+ if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
trace_usb_ehci_packet_action(p->queue, p, "remove");
ehci_free_packet(p);
return;
trace_usb_ehci_packet_action(p->queue, p, "wakeup");
p->async = EHCI_ASYNC_FINISHED;
- p->usb_status = packet->result;
+ p->usb_status = packet->status ? packet->status : packet->actual_length;
if (p->queue->async) {
qemu_bh_schedule(p->queue->ehci->async_bh);
static int ehci_execute(EHCIPacket *p, const char *action)
{
USBEndpoint *ep;
- int ret;
int endp;
bool spd;
}
trace_usb_ehci_packet_action(p->queue, p, action);
- ret = usb_handle_packet(p->queue->dev, &p->packet);
- DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd endp %x ret %d\n",
- q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
- q->packet.iov.size, endp, ret);
+ usb_handle_packet(p->queue->dev, &p->packet);
+ DPRINTF("submit: qh 0x%x next 0x%x qtd 0x%x pid 0x%x len %zd endp 0x%x "
+ "status %d actual_length %d\n", p->queue->qhaddr, p->qtd.next,
+ p->qtdaddr, p->pid, p->packet.iov.size, endp, p->packet.status,
+ p->packet.actual_length);
- if (ret > BUFF_SIZE) {
+ if (p->packet.actual_length > BUFF_SIZE) {
fprintf(stderr, "ret from usb_handle_packet > BUFF_SIZE\n");
return USB_RET_PROCERR;
}
- return ret;
+ if (p->packet.status == USB_RET_SUCCESS) {
+ return p->packet.actual_length;
+ } else {
+ return p->packet.status;
+ }
}
/* 4.7.2
usb_packet_setup(&ehci->ipacket, pid, ep, addr, false,
(itd->transact[i] & ITD_XACT_IOC) != 0);
usb_packet_map(&ehci->ipacket, &ehci->isgl);
- ret = usb_handle_packet(dev, &ehci->ipacket);
+ usb_handle_packet(dev, &ehci->ipacket);
usb_packet_unmap(&ehci->ipacket, &ehci->isgl);
+ ret = (ehci->ipacket.status == USB_RET_SUCCESS) ?
+ ehci->ipacket.actual_length : ehci->ipacket.status;
} else {
DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
ret = USB_RET_NAK;
{
USBDevice *dev;
USBEndpoint *uep;
- int ret;
int idx = epnum && dir;
int ttype;
ep->packey[dir].ep = ep;
ep->packey[dir].dir = dir;
- ret = usb_handle_packet(dev, &ep->packey[dir].p);
+ usb_handle_packet(dev, &ep->packey[dir].p);
- if (ret == USB_RET_ASYNC) {
+ if (ep->packey[dir].p.status == USB_RET_ASYNC) {
usb_device_flush_ep_queue(dev, uep);
ep->status[dir] = len;
return;
}
- ep->status[dir] = ret;
+ if (ep->packey[dir].p.status == USB_RET_SUCCESS) {
+ ep->status[dir] = ep->packey[dir].p.actual_length;
+ } else {
+ ep->status[dir] = ep->packey[dir].p.status;
+ }
musb_schedule_cb(&s->port, &ep->packey[dir].p);
}
if (ep->status[1] == USB_RET_STALL) {
ep->status[1] = 0;
- packey->result = 0;
ep->csr[1] |= MGC_M_RXCSR_H_RXSTALL;
if (!epnum)
/* TODO: check len for over/underruns of an OUT packet? */
/* TODO: perhaps make use of e->ext_size[1] here. */
- packey->result = ep->status[1];
-
if (!(ep->csr[1] & (MGC_M_RXCSR_H_RXSTALL | MGC_M_RXCSR_DATAERROR))) {
ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
if (!epnum)
ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
- ep->rxcount = packey->result; /* XXX: MIN(packey->len, ep->maxp[1]); */
+ ep->rxcount = ep->status[1]; /* XXX: MIN(packey->len, ep->maxp[1]); */
/* In DMA mode: assert DMA request for this EP */
}
DMA_DIRECTION_TO_DEVICE);
}
- if (completion) {
- ret = ohci->usb_packet.result;
- } else {
+ if (!completion) {
bool int_req = relative_frame_number == frame_count &&
OHCI_BM(iso_td.flags, TD_DI) == 0;
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
usb_packet_setup(&ohci->usb_packet, pid, ep, addr, false, int_req);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
- ret = usb_handle_packet(dev, &ohci->usb_packet);
- if (ret == USB_RET_ASYNC) {
+ usb_handle_packet(dev, &ohci->usb_packet);
+ if (ohci->usb_packet.status == USB_RET_ASYNC) {
usb_device_flush_ep_queue(dev, ep);
return 1;
}
}
+ if (ohci->usb_packet.status == USB_RET_SUCCESS) {
+ ret = ohci->usb_packet.actual_length;
+ } else {
+ ret = ohci->usb_packet.status;
+ }
#ifdef DEBUG_ISOCH
printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n",
}
#endif
if (completion) {
- ret = ohci->usb_packet.result;
ohci->async_td = 0;
ohci->async_complete = 0;
} else {
usb_packet_setup(&ohci->usb_packet, pid, ep, addr, !flag_r,
OHCI_BM(td.flags, TD_DI) == 0);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
- ret = usb_handle_packet(dev, &ohci->usb_packet);
+ usb_handle_packet(dev, &ohci->usb_packet);
#ifdef DEBUG_PACKET
- DPRINTF("ret=%d\n", ret);
+ DPRINTF("status=%d\n", ohci->usb_packet.status);
#endif
- if (ret == USB_RET_ASYNC) {
+ if (ohci->usb_packet.status == USB_RET_ASYNC) {
usb_device_flush_ep_queue(dev, ep);
ohci->async_td = addr;
return 1;
}
}
+ if (ohci->usb_packet.status == USB_RET_SUCCESS) {
+ ret = ohci->usb_packet.actual_length;
+ } else {
+ ret = ohci->usb_packet.status;
+ }
+
if (ret >= 0) {
if (dir == OHCI_TD_DIR_IN) {
ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
{
- int len = 0, max_len, ret;
+ int len = 0, max_len;
uint8_t pid;
max_len = ((td->token >> 21) + 1) & 0x7ff;
pid = td->token & 0xff;
- ret = async->packet.result;
-
if (td->ctrl & TD_CTRL_IOS)
td->ctrl &= ~TD_CTRL_ACTIVE;
- if (ret < 0) {
- return uhci_handle_td_error(s, td, async->td_addr, ret, int_mask);
+ if (async->packet.status != USB_RET_SUCCESS) {
+ return uhci_handle_td_error(s, td, async->td_addr,
+ async->packet.status, int_mask);
}
- len = async->packet.result;
+ len = async->packet.actual_length;
td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
/* The NAK bit may have been set by a previous frame, so clear it
static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask)
{
- int len = 0, max_len;
+ int ret, max_len;
bool spd;
bool queuing = (q != NULL);
uint8_t pid = td->token & 0xff;
switch(pid) {
case USB_TOKEN_OUT:
case USB_TOKEN_SETUP:
- len = usb_handle_packet(q->ep->dev, &async->packet);
- if (len >= 0)
- len = max_len;
+ usb_handle_packet(q->ep->dev, &async->packet);
+ if (async->packet.status == USB_RET_SUCCESS) {
+ async->packet.actual_length = max_len;
+ }
break;
case USB_TOKEN_IN:
- len = usb_handle_packet(q->ep->dev, &async->packet);
+ usb_handle_packet(q->ep->dev, &async->packet);
break;
default:
uhci_update_irq(s);
return TD_RESULT_STOP_FRAME;
}
-
- if (len == USB_RET_ASYNC) {
+
+ if (async->packet.status == USB_RET_ASYNC) {
uhci_async_link(async);
if (!queuing) {
uhci_queue_fill(q, td);
return TD_RESULT_ASYNC_START;
}
- async->packet.result = len;
-
done:
- len = uhci_complete_td(s, td, async, int_mask);
+ ret = uhci_complete_td(s, td, async, int_mask);
usb_packet_unmap(&async->packet, &async->sgl);
uhci_async_free(async);
- return len;
+ return ret;
}
static void uhci_async_complete(USBPort *port, USBPacket *packet)
UHCIAsync *async = container_of(packet, UHCIAsync, packet);
UHCIState *s = async->queue->uhci;
- if (packet->result == USB_RET_REMOVE_FROM_QUEUE) {
+ if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
uhci_async_unlink(async);
uhci_async_cancel(async);
return;
XHCIState *xhci = xfer->xhci;
int i;
- left = xfer->packet.result < 0 ? 0 : xfer->packet.result;
+ left = xfer->packet.status ? 0 : xfer->packet.actual_length;
for (i = 0; i < xfer->trb_count; i++) {
XHCITRB *trb = &xfer->trbs[i];
return 0;
}
-static int xhci_complete_packet(XHCITransfer *xfer, int ret)
+static int xhci_complete_packet(XHCITransfer *xfer)
{
- if (ret == USB_RET_ASYNC) {
+ if (xfer->packet.status == USB_RET_ASYNC) {
trace_usb_xhci_xfer_async(xfer);
xfer->running_async = 1;
xfer->running_retry = 0;
xfer->complete = 0;
xfer->cancelled = 0;
return 0;
- } else if (ret == USB_RET_NAK) {
+ } else if (xfer->packet.status == USB_RET_NAK) {
trace_usb_xhci_xfer_nak(xfer);
xfer->running_async = 0;
xfer->running_retry = 1;
xhci_xfer_unmap(xfer);
}
- if (ret >= 0) {
- trace_usb_xhci_xfer_success(xfer, ret);
+ if (xfer->packet.status == USB_RET_SUCCESS) {
+ trace_usb_xhci_xfer_success(xfer, xfer->packet.actual_length);
xfer->status = CC_SUCCESS;
xhci_xfer_report(xfer);
return 0;
}
/* error */
- trace_usb_xhci_xfer_error(xfer, ret);
- switch (ret) {
+ trace_usb_xhci_xfer_error(xfer, xfer->packet.status);
+ switch (xfer->packet.status) {
case USB_RET_NODEV:
xfer->status = CC_USB_TRANSACTION_ERROR;
xhci_xfer_report(xfer);
xhci_stall_ep(xfer);
break;
default:
- fprintf(stderr, "%s: FIXME: ret = %d\n", __FUNCTION__, ret);
+ fprintf(stderr, "%s: FIXME: status = %d\n", __func__,
+ xfer->packet.status);
FIXME();
}
return 0;
{
XHCITRB *trb_setup, *trb_status;
uint8_t bmRequestType;
- int ret;
trb_setup = &xfer->trbs[0];
trb_status = &xfer->trbs[xfer->trb_count-1];
}
xfer->packet.parameter = trb_setup->parameter;
- ret = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+ usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
- xhci_complete_packet(xfer, ret);
+ xhci_complete_packet(xfer);
if (!xfer->running_async && !xfer->running_retry) {
xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
}
static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
{
uint64_t mfindex;
- int ret;
DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
if (xhci_setup_packet(xfer) < 0) {
return -1;
}
- ret = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+ usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
- xhci_complete_packet(xfer, ret);
+ xhci_complete_packet(xfer);
if (!xfer->running_async && !xfer->running_retry) {
xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
}
if (epctx->retry) {
XHCITransfer *xfer = epctx->retry;
- int result;
trace_usb_xhci_xfer_retry(xfer);
assert(xfer->running_retry);
if (xhci_setup_packet(xfer) < 0) {
return;
}
- result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
- assert(result != USB_RET_NAK);
- xhci_complete_packet(xfer, result);
+ usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+ assert(xfer->packet.status != USB_RET_NAK);
+ xhci_complete_packet(xfer);
} else {
/* retry nak'ed transfer */
if (xhci_setup_packet(xfer) < 0) {
return;
}
- result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
- if (result == USB_RET_NAK) {
+ usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+ if (xfer->packet.status == USB_RET_NAK) {
return;
}
- xhci_complete_packet(xfer, result);
+ xhci_complete_packet(xfer);
}
assert(!xfer->running_retry);
epctx->retry = NULL;
{
XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
- if (packet->result == USB_RET_REMOVE_FROM_QUEUE) {
+ if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
xhci_ep_nuke_one_xfer(xfer);
return;
}
- xhci_complete_packet(xfer, packet->result);
+ xhci_complete_packet(xfer);
xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid);
}
* -check device states against transfer requests
* and return appropriate response
*/
-static int usb_host_handle_control(USBDevice *dev,
+static void usb_host_handle_control(USBDevice *dev,
USBPacket *p,
int request,
int value,
/* specific SET_ADDRESS support */
dev->addr = value;
- return 0;
} else if ((request >> 8) == UT_WRITE_DEVICE &&
(request & 0xff) == UR_SET_CONFIG) {
printf("handle_control: failed to set configuration - %s\n",
strerror(errno));
#endif
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
-
- return 0;
} else if ((request >> 8) == UT_WRITE_INTERFACE &&
(request & 0xff) == UR_SET_INTERFACE) {
printf("handle_control: failed to set alternate interface - %s\n",
strerror(errno));
#endif
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
-
- return 0;
} else {
req.ucr_request.bmRequestType = request >> 8;
req.ucr_request.bRequest = request & 0xff;
printf("handle_control: error after request - %s\n",
strerror(errno));
#endif
- return USB_RET_NAK; // STALL
+ p->status = USB_RET_NAK; /* STALL */
} else {
- return req.ucr_actlen;
+ p->actual_length = req.ucr_actlen;
}
}
}
-static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_host_handle_data(USBDevice *dev, USBPacket *p)
{
USBHostDevice *s = (USBHostDevice *)dev;
int ret, fd, mode;
fd = ensure_ep_open(s, devep, mode);
if (fd < 0) {
sigprocmask(SIG_SETMASK, &old_mask, NULL);
- return USB_RET_NODEV;
+ p->status = USB_RET_NODEV;
+ return;
}
if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
switch(errno) {
case ETIMEDOUT:
case EINTR:
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
+ break;
default:
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
} else {
- return ret;
+ p->actual_length = ret;
}
}
if (p) {
switch (aurb->urb.status) {
case 0:
- p->result += aurb->urb.actual_length;
+ p->actual_length = aurb->urb.actual_length;
+ p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
break;
case -EPIPE:
set_halt(s, p->pid, p->ep->nr);
- p->result = USB_RET_STALL;
+ p->status = USB_RET_STALL;
break;
case -EOVERFLOW:
- p->result = USB_RET_BABBLE;
+ p->status = USB_RET_BABBLE;
break;
default:
- p->result = USB_RET_IOERROR;
+ p->status = USB_RET_IOERROR;
break;
}
if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
- trace_usb_host_req_complete(s->bus_num, s->addr, p, p->result);
+ trace_usb_host_req_complete(s->bus_num, s->addr, p, p->status);
usb_generic_async_ctrl_complete(&s->dev, p);
} else if (!aurb->more) {
- trace_usb_host_req_complete(s->bus_num, s->addr, p, p->result);
+ trace_usb_host_req_complete(s->bus_num, s->addr, p, p->status);
usb_packet_complete(&s->dev, p);
}
}
clear_iso_started(s, pid, ep);
}
-static int urb_status_to_usb_ret(int status)
+static void urb_status_to_usb_ret(int status, USBPacket *p)
{
switch (status) {
case -EPIPE:
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ break;
case -EOVERFLOW:
- return USB_RET_BABBLE;
+ p->status = USB_RET_BABBLE;
+ break;
default:
- return USB_RET_IOERROR;
+ p->status = USB_RET_IOERROR;
}
}
-static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
+static void usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
{
AsyncURB *aurb;
- int i, j, ret, max_packet_size, offset, len = 0;
+ int i, j, max_packet_size, offset, len;
uint8_t *buf;
max_packet_size = p->ep->max_packet_size;
- if (max_packet_size == 0)
- return USB_RET_NAK;
+ if (max_packet_size == 0) {
+ p->status = USB_RET_NAK;
+ return;
+ }
aurb = get_iso_urb(s, p->pid, p->ep->nr);
if (!aurb) {
if (in) {
/* Check urb status */
if (aurb[i].urb.status) {
- len = urb_status_to_usb_ret(aurb[i].urb.status);
+ urb_status_to_usb_ret(aurb[i].urb.status, p);
/* Move to the next urb */
aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
/* Check frame status */
} else if (aurb[i].urb.iso_frame_desc[j].status) {
- len = urb_status_to_usb_ret(
- aurb[i].urb.iso_frame_desc[j].status);
+ urb_status_to_usb_ret(aurb[i].urb.iso_frame_desc[j].status, p);
/* Check the frame fits */
} else if (aurb[i].urb.iso_frame_desc[j].actual_length
> p->iov.size) {
printf("husb: received iso data is larger then packet\n");
- len = USB_RET_BABBLE;
+ p->status = USB_RET_BABBLE;
/* All good copy data over */
} else {
len = aurb[i].urb.iso_frame_desc[j].actual_length;
/* Check the frame fits */
if (len > max_packet_size) {
printf("husb: send iso data is larger then max packet size\n");
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
+ return;
}
/* All good copy data over */
/* (Re)-submit all fully consumed / filled urbs */
for (i = 0; i < s->iso_urb_count; i++) {
if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
- ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
- if (ret < 0) {
+ if (ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]) < 0) {
perror("USBDEVFS_SUBMITURB");
- if (!in || len == 0) {
+ if (!in || p->status == USB_RET_SUCCESS) {
switch(errno) {
case ETIMEDOUT:
- len = USB_RET_NAK;
+ p->status = USB_RET_NAK;
break;
case EPIPE:
default:
- len = USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
}
break;
}
}
}
-
- return len;
}
-static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
+static void usb_host_handle_data(USBDevice *dev, USBPacket *p)
{
USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
struct usbdevfs_urb *urb;
if (!is_valid(s, p->pid, p->ep->nr)) {
trace_usb_host_req_complete(s->bus_num, s->addr, p, USB_RET_NAK);
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
+ return;
}
if (p->pid == USB_TOKEN_IN) {
if (ret < 0) {
perror("USBDEVFS_CLEAR_HALT");
trace_usb_host_req_complete(s->bus_num, s->addr, p, USB_RET_NAK);
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
+ return;
}
clear_halt(s, p->pid, p->ep->nr);
}
if (is_isoc(s, p->pid, p->ep->nr)) {
- return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
+ usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
+ return;
}
v = 0;
case ETIMEDOUT:
trace_usb_host_req_complete(s->bus_num, s->addr, p,
USB_RET_NAK);
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
+ break;
case EPIPE:
default:
trace_usb_host_req_complete(s->bus_num, s->addr, p,
USB_RET_STALL);
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
}
+ return;
}
} while (rem > 0);
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
static int ctrl_error(void)
}
}
-static int usb_host_set_address(USBHostDevice *s, int addr)
+static void usb_host_set_address(USBHostDevice *s, int addr)
{
trace_usb_host_set_address(s->bus_num, s->addr, addr);
s->dev.addr = addr;
- return 0;
}
-static int usb_host_set_config(USBHostDevice *s, int config)
+static void usb_host_set_config(USBHostDevice *s, int config, USBPacket *p)
{
int ret, first = 1;
}
if (ret < 0) {
- return ctrl_error();
+ p->status = ctrl_error();
+ return;
}
usb_host_claim_interfaces(s, config);
usb_linux_update_endp_table(s);
- return 0;
}
-static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
+static void usb_host_set_interface(USBHostDevice *s, int iface, int alt,
+ USBPacket *p)
{
struct usbdevfs_setinterface si;
int i, ret;
}
if (iface >= USB_MAX_INTERFACES) {
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ return;
}
si.interface = iface;
iface, alt, ret, errno);
if (ret < 0) {
- return ctrl_error();
+ p->status = ctrl_error();
+ return;
}
s->dev.altsetting[iface] = alt;
usb_linux_update_endp_table(s);
- return 0;
}
-static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
+static void usb_host_handle_control(USBDevice *dev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
switch (request) {
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- ret = usb_host_set_address(s, value);
- trace_usb_host_req_emulated(s->bus_num, s->addr, p, ret);
- return ret;
+ usb_host_set_address(s, value);
+ trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status);
+ return;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- ret = usb_host_set_config(s, value & 0xff);
- trace_usb_host_req_emulated(s->bus_num, s->addr, p, ret);
- return ret;
+ usb_host_set_config(s, value & 0xff, p);
+ trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status);
+ return;
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
- ret = usb_host_set_interface(s, index, value);
- trace_usb_host_req_emulated(s->bus_num, s->addr, p, ret);
- return ret;
+ usb_host_set_interface(s, index, value, p);
+ trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status);
+ return;
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
if (value == 0) { /* clear halt */
ioctl(s->fd, USBDEVFS_CLEAR_HALT, &index);
clear_halt(s, pid, index & 0x0f);
trace_usb_host_req_emulated(s->bus_num, s->addr, p, 0);
- return 0;
+ return;
}
}
/* The rest are asynchronous */
- assert(p && p->result == 0);
-
if (length > sizeof(dev->data_buf)) {
fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
length, sizeof(dev->data_buf));
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ return;
}
aurb = async_alloc(s);
switch(errno) {
case ETIMEDOUT:
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
+ break;
case EPIPE:
default:
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ break;
}
+ return;
}
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
/* returns 1 on problem encountered or 0 for success */
struct usb_redir_interrupt_packet_header *interrupt_header,
uint8_t *data, int data_len);
-static int usbredir_handle_status(USBRedirDevice *dev,
- int status, int actual_len);
+static void usbredir_handle_status(USBRedirDevice *dev, USBPacket *p,
+ int status);
#define VERSION "qemu usb-redir guest " QEMU_VERSION
usbredirparser_do_write(dev->parser);
}
-static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
uint8_t ep)
{
int status, len;
!dev->endpoint[EP2I(ep)].bufpq_prefilled) {
if (dev->endpoint[EP2I(ep)].bufpq_size <
dev->endpoint[EP2I(ep)].bufpq_target_size) {
- return usbredir_handle_status(dev, 0, 0);
+ return;
}
dev->endpoint[EP2I(ep)].bufpq_prefilled = 1;
}
/* Check iso_error for stream errors, otherwise its an underrun */
status = dev->endpoint[EP2I(ep)].iso_error;
dev->endpoint[EP2I(ep)].iso_error = 0;
- return status ? USB_RET_IOERROR : 0;
+ p->status = status ? USB_RET_IOERROR : USB_RET_SUCCESS;
+ return;
}
DPRINTF2("iso-token-in ep %02X status %d len %d queue-size: %d\n", ep,
isop->status, isop->len, dev->endpoint[EP2I(ep)].bufpq_size);
status = isop->status;
if (status != usb_redir_success) {
bufp_free(dev, isop, ep);
- return USB_RET_IOERROR;
+ p->status = USB_RET_IOERROR;
+ return;
}
len = isop->len;
ERROR("received iso data is larger then packet ep %02X (%d > %d)\n",
ep, len, (int)p->iov.size);
bufp_free(dev, isop, ep);
- return USB_RET_BABBLE;
+ p->status = USB_RET_BABBLE;
+ return;
}
usb_packet_copy(p, isop->data, len);
bufp_free(dev, isop, ep);
- return len;
} else {
/* If the stream was not started because of a pending error don't
send the packet to the usb-host */
dev->endpoint[EP2I(ep)].iso_error = 0;
DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status,
p->iov.size);
- return usbredir_handle_status(dev, status, p->iov.size);
+ usbredir_handle_status(dev, p, status);
}
}
usbredir_free_bufpq(dev, ep);
}
-static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
uint8_t ep)
{
struct usb_redir_bulk_packet_header bulk_packet;
DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, size, p->id);
if (usbredir_already_in_flight(dev, p->id)) {
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
+ return;
}
bulk_packet.endpoint = ep;
&bulk_packet, buf, size);
}
usbredirparser_do_write(dev->parser);
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
-static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
+static void usbredir_handle_interrupt_data(USBRedirDevice *dev,
USBPacket *p, uint8_t ep)
{
if (ep & USB_DIR_IN) {
status = dev->endpoint[EP2I(ep)].interrupt_error;
dev->endpoint[EP2I(ep)].interrupt_error = 0;
if (status) {
- return usbredir_handle_status(dev, status, 0);
+ usbredir_handle_status(dev, p, status);
+ } else {
+ p->status = USB_RET_NAK;
}
- return USB_RET_NAK;
+ return;
}
DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
intp->status, intp->len);
status = intp->status;
if (status != usb_redir_success) {
bufp_free(dev, intp, ep);
- return usbredir_handle_status(dev, status, 0);
+ usbredir_handle_status(dev, p, status);
+ return;
}
len = intp->len;
if (len > p->iov.size) {
ERROR("received int data is larger then packet ep %02X\n", ep);
bufp_free(dev, intp, ep);
- return USB_RET_BABBLE;
+ p->status = USB_RET_BABBLE;
+ return;
}
usb_packet_copy(p, intp->data, len);
bufp_free(dev, intp, ep);
- return len;
} else {
/* Output interrupt endpoint, normal async operation */
struct usb_redir_interrupt_packet_header interrupt_packet;
p->iov.size, p->id);
if (usbredir_already_in_flight(dev, p->id)) {
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
+ return;
}
interrupt_packet.endpoint = ep;
usbredirparser_send_interrupt_packet(dev->parser, p->id,
&interrupt_packet, buf, p->iov.size);
usbredirparser_do_write(dev->parser);
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
}
usbredir_free_bufpq(dev, ep);
}
-static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
+static void usbredir_handle_data(USBDevice *udev, USBPacket *p)
{
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
uint8_t ep;
switch (dev->endpoint[EP2I(ep)].type) {
case USB_ENDPOINT_XFER_CONTROL:
ERROR("handle_data called for control transfer on ep %02X\n", ep);
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
+ break;
case USB_ENDPOINT_XFER_ISOC:
- return usbredir_handle_iso_data(dev, p, ep);
+ usbredir_handle_iso_data(dev, p, ep);
+ break;
case USB_ENDPOINT_XFER_BULK:
if (p->state == USB_PACKET_SETUP && p->pid == USB_TOKEN_IN &&
p->ep->pipeline) {
- return USB_RET_ADD_TO_QUEUE;
+ p->status = USB_RET_ADD_TO_QUEUE;
+ break;
}
- return usbredir_handle_bulk_data(dev, p, ep);
+ usbredir_handle_bulk_data(dev, p, ep);
+ break;
case USB_ENDPOINT_XFER_INT:
- return usbredir_handle_interrupt_data(dev, p, ep);
+ usbredir_handle_interrupt_data(dev, p, ep);
+ break;
default:
ERROR("handle_data ep %02X has unknown type %d\n", ep,
dev->endpoint[EP2I(ep)].type);
- return USB_RET_NAK;
+ p->status = USB_RET_NAK;
}
}
}
}
-static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
int config)
{
struct usb_redir_set_configuration_header set_config;
set_config.configuration = config;
usbredirparser_send_set_configuration(dev->parser, p->id, &set_config);
usbredirparser_do_write(dev->parser);
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
-static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
+static void usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
{
DPRINTF("get config id %"PRIu64"\n", p->id);
usbredirparser_send_get_configuration(dev->parser, p->id);
usbredirparser_do_write(dev->parser);
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
-static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
int interface, int alt)
{
struct usb_redir_set_alt_setting_header set_alt;
set_alt.alt = alt;
usbredirparser_send_set_alt_setting(dev->parser, p->id, &set_alt);
usbredirparser_do_write(dev->parser);
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
-static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
+static void usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
int interface)
{
struct usb_redir_get_alt_setting_header get_alt;
get_alt.interface = interface;
usbredirparser_send_get_alt_setting(dev->parser, p->id, &get_alt);
usbredirparser_do_write(dev->parser);
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
-static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
+static void usbredir_handle_control(USBDevice *udev, USBPacket *p,
int request, int value, int index, int length, uint8_t *data)
{
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
struct usb_redir_control_packet_header control_packet;
if (usbredir_already_in_flight(dev, p->id)) {
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
+ return;
}
/* Special cases for certain standard device requests */
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
DPRINTF("set address %d\n", value);
dev->dev.addr = value;
- return 0;
+ return;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- return usbredir_set_config(dev, p, value & 0xff);
+ usbredir_set_config(dev, p, value & 0xff);
+ return;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- return usbredir_get_config(dev, p);
+ usbredir_get_config(dev, p);
+ return;
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
- return usbredir_set_interface(dev, p, index, value);
+ usbredir_set_interface(dev, p, index, value);
+ return;
case InterfaceRequest | USB_REQ_GET_INTERFACE:
- return usbredir_get_interface(dev, p, index);
+ usbredir_get_interface(dev, p, index);
+ return;
}
/* Normal ctrl requests, note request is (bRequestType << 8) | bRequest */
&control_packet, data, length);
}
usbredirparser_do_write(dev->parser);
- return USB_RET_ASYNC;
+ p->status = USB_RET_ASYNC;
}
/*
* usbredirparser packet complete callbacks
*/
-static int usbredir_handle_status(USBRedirDevice *dev,
- int status, int actual_len)
+static void usbredir_handle_status(USBRedirDevice *dev, USBPacket *p,
+ int status)
{
switch (status) {
case usb_redir_success:
- return actual_len;
+ p->status = USB_RET_SUCCESS; /* Clear previous ASYNC status */
+ break;
case usb_redir_stall:
- return USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ break;
case usb_redir_cancelled:
/*
* When the usbredir-host unredirects a device, it will report a status
* of cancelled for all pending packets, followed by a disconnect msg.
*/
- return USB_RET_IOERROR;
+ p->status = USB_RET_IOERROR;
+ break;
case usb_redir_inval:
WARNING("got invalid param error from usb-host?\n");
- return USB_RET_IOERROR;
+ p->status = USB_RET_IOERROR;
+ break;
case usb_redir_babble:
- return USB_RET_BABBLE;
+ p->status = USB_RET_BABBLE;
+ break;
case usb_redir_ioerror:
case usb_redir_timeout:
default:
- return USB_RET_IOERROR;
+ p->status = USB_RET_IOERROR;
}
}
{
USBRedirDevice *dev = priv;
USBPacket *p;
- int len = 0;
DPRINTF("set config status %d config %d id %"PRIu64"\n",
config_status->status, config_status->configuration, id);
if (p) {
if (dev->dev.setup_buf[0] & USB_DIR_IN) {
dev->dev.data_buf[0] = config_status->configuration;
- len = 1;
+ p->actual_length = 1;
}
- p->result = usbredir_handle_status(dev, config_status->status, len);
+ usbredir_handle_status(dev, p, config_status->status);
usb_generic_async_ctrl_complete(&dev->dev, p);
}
}
{
USBRedirDevice *dev = priv;
USBPacket *p;
- int len = 0;
DPRINTF("alt status %d intf %d alt %d id: %"PRIu64"\n",
alt_setting_status->status, alt_setting_status->interface,
if (p) {
if (dev->dev.setup_buf[0] & USB_DIR_IN) {
dev->dev.data_buf[0] = alt_setting_status->alt;
- len = 1;
+ p->actual_length = 1;
}
- p->result =
- usbredir_handle_status(dev, alt_setting_status->status, len);
+ usbredir_handle_status(dev, p, alt_setting_status->status);
usb_generic_async_ctrl_complete(&dev->dev, p);
}
}
p = usbredir_find_packet_by_id(dev, 0, id);
if (p) {
- len = usbredir_handle_status(dev, control_packet->status, len);
- if (len > 0) {
+ usbredir_handle_status(dev, p, control_packet->status);
+ if (p->status == USB_RET_SUCCESS) {
usbredir_log_data(dev, "ctrl data in:", data, data_len);
if (data_len <= sizeof(dev->dev.data_buf)) {
memcpy(dev->dev.data_buf, data, data_len);
} else {
ERROR("ctrl buffer too small (%d > %zu)\n",
data_len, sizeof(dev->dev.data_buf));
- len = USB_RET_STALL;
+ p->status = USB_RET_STALL;
+ len = 0;
}
}
- p->result = len;
+ p->actual_length = len;
usb_generic_async_ctrl_complete(&dev->dev, p);
}
free(data);
p = usbredir_find_packet_by_id(dev, ep, id);
if (p) {
size_t size = (p->combined) ? p->combined->iov.size : p->iov.size;
- len = usbredir_handle_status(dev, bulk_packet->status, len);
- if (len > 0) {
+ usbredir_handle_status(dev, p, bulk_packet->status);
+ if (p->status == USB_RET_SUCCESS) {
usbredir_log_data(dev, "bulk data in:", data, data_len);
if (data_len <= size) {
if (p->combined) {
} else {
ERROR("bulk got more data then requested (%d > %zd)\n",
data_len, p->iov.size);
- len = USB_RET_BABBLE;
+ p->status = USB_RET_BABBLE;
+ len = 0;
}
}
- p->result = len;
+ p->actual_length = len;
if (p->pid == USB_TOKEN_IN && p->ep->pipeline) {
usb_combined_input_packet_complete(&dev->dev, p);
} else {
USBPacket *p = usbredir_find_packet_by_id(dev, ep, id);
if (p) {
- p->result = usbredir_handle_status(dev,
- interrupt_packet->status, len);
+ usbredir_handle_status(dev, p, interrupt_packet->status);
+ p->actual_length = len;
usb_packet_complete(&dev->dev, p);
}
}