diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-14 08:50:18 -0600 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-14 08:50:18 -0600 |
commit | ce5e5b522e8d3b848b6445c34226b69c77c46403 (patch) | |
tree | 9cd13246a20784e657c3d6d686e0282d1da5ffba /hw | |
parent | bf0dfb69f860a7894958068fba45f5268dddd6be (diff) | |
parent | 9d1530470bba5d8bec4796c0b43b874d5f9ef017 (diff) | |
download | qemu-ce5e5b522e8d3b848b6445c34226b69c77c46403.zip qemu-ce5e5b522e8d3b848b6445c34226b69c77c46403.tar.gz qemu-ce5e5b522e8d3b848b6445c34226b69c77c46403.tar.bz2 |
Merge remote-tracking branch 'kraxel/usb.70' into staging
* kraxel/usb.70:
ehci: fix migration
xhci: Fix some DMA host endian bugs
usb/combined-packet: Move freeing of combined to usb_combined_packet_remove()
xhci: Add support for packets with both data and an error status
ehci: Add support for packets with both data and an error status
ehci: Get rid of the magical PROC_ERR status
usb-redir: Allow packets to have both data and an error-status
usb: split packet result into actual_length + status
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/usb.h | 24 | ||||
-rw-r--r-- | hw/usb/bus.c | 13 | ||||
-rw-r--r-- | hw/usb/combined-packet.c | 58 | ||||
-rw-r--r-- | hw/usb/core.c | 209 | ||||
-rw-r--r-- | hw/usb/desc.c | 16 | ||||
-rw-r--r-- | hw/usb/desc.h | 3 | ||||
-rw-r--r-- | hw/usb/dev-audio.c | 49 | ||||
-rw-r--r-- | hw/usb/dev-bluetooth.c | 33 | ||||
-rw-r--r-- | hw/usb/dev-hid.c | 42 | ||||
-rw-r--r-- | hw/usb/dev-hub.c | 34 | ||||
-rw-r--r-- | hw/usb/dev-network.c | 101 | ||||
-rw-r--r-- | hw/usb/dev-serial.c | 29 | ||||
-rw-r--r-- | hw/usb/dev-smartcard-reader.c | 69 | ||||
-rw-r--r-- | hw/usb/dev-storage.c | 51 | ||||
-rw-r--r-- | hw/usb/dev-uas.c | 36 | ||||
-rw-r--r-- | hw/usb/dev-wacom.c | 38 | ||||
-rw-r--r-- | hw/usb/hcd-ehci-pci.c | 3 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.c | 216 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.h | 1 | ||||
-rw-r--r-- | hw/usb/hcd-musb.c | 16 | ||||
-rw-r--r-- | hw/usb/hcd-ohci.c | 26 | ||||
-rw-r--r-- | hw/usb/hcd-uhci.c | 34 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 129 | ||||
-rw-r--r-- | hw/usb/host-bsd.c | 27 | ||||
-rw-r--r-- | hw/usb/host-linux.c | 128 | ||||
-rw-r--r-- | hw/usb/redirect.c | 187 |
26 files changed, 775 insertions, 797 deletions
@@ -38,6 +38,7 @@ #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) @@ -280,18 +281,20 @@ typedef struct USBDeviceClass { * 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); @@ -354,7 +357,8 @@ struct USBPacket { 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; @@ -388,7 +392,7 @@ static inline bool usb_packet_is_inflight(USBPacket *p) 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); @@ -523,10 +527,10 @@ void usb_device_handle_attach(USBDevice *dev); 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); diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 8066291..99aac7a 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -140,24 +140,21 @@ 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 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) diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c index 3904e71..4a0c299 100644 --- a/hw/usb/combined-packet.c +++ b/hw/usb/combined-packet.c @@ -31,12 +31,16 @@ static void usb_combined_packet_add(USBCombinedPacket *combined, USBPacket *p) p->combined = combined; } +/* Note will free combined when the last packet gets removed */ static void usb_combined_packet_remove(USBCombinedPacket *combined, USBPacket *p) { assert(p->combined == combined); p->combined = NULL; QTAILQ_REMOVE(&combined->packets, p, combined_entry); + if (QTAILQ_EMPTY(&combined->packets)) { + g_free(combined); + } } /* Also handles completion of non combined packets for pipelined input eps */ @@ -45,9 +49,8 @@ void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p) USBCombinedPacket *combined = p->combined; USBEndpoint *ep = p->ep; USBPacket *next; - enum { completing, complete, leftover }; - int result, state = completing; - bool short_not_ok; + int status, actual_length; + bool short_not_ok, done = false; if (combined == NULL) { usb_packet_complete_one(dev, p); @@ -56,37 +59,39 @@ void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p) 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) { + if (!done) { /* 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; - state = complete; + p->actual_length = actual_length; + done = true; + } + /* Report status on the last packet */ + if (done || next == NULL) { + p->status = status; + } else { + p->status = USB_RET_SUCCESS; } p->short_not_ok = short_not_ok; + /* Note will free combined when the last packet gets removed! */ 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; + /* Note will free combined on the last packet! */ dev->port->ops->complete(dev->port, p); } } - /* - * If we had leftover packets the hcd driver will have cancelled them - * and usb_combined_packet_cancel has already freed combined! - */ - if (state != leftover) { - g_free(combined); - } + /* Do not use combined here, it has been freed! */ leave: /* Check if there are packets in the queue waiting for our completion */ usb_ep_combine_input_packets(ep); @@ -97,14 +102,13 @@ void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p) { USBCombinedPacket *combined = p->combined; assert(combined != NULL); + USBPacket *first = p->combined->first; + /* Note will free combined on the last packet! */ usb_combined_packet_remove(combined, p); - if (p == combined->first) { + if (p == first) { usb_device_cancel_packet(dev, p); } - if (QTAILQ_EMPTY(&combined->packets)) { - g_free(combined); - } } /* @@ -117,7 +121,7 @@ void usb_ep_combine_input_packets(USBEndpoint *ep) { 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); @@ -125,7 +129,7 @@ void usb_ep_combine_input_packets(USBEndpoint *ep) 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; } @@ -166,8 +170,8 @@ void usb_ep_combine_input_packets(USBEndpoint *ep) 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); diff --git a/hw/usb/core.c b/hw/usb/core.c index ab37f6f..52b5310 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -97,17 +97,17 @@ void usb_wakeup(USBEndpoint *ep) #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; @@ -116,24 +116,26 @@ static int do_token_setup(USBDevice *s, USBPacket *p) 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; @@ -141,13 +143,12 @@ static int do_token_setup(USBDevice *s, USBPacket *p) 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); @@ -158,19 +159,15 @@ static int do_token_in(USBDevice *s, USBPacket *p) 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) { @@ -180,20 +177,21 @@ static int do_token_in(USBDevice *s, USBPacket *p) } 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); @@ -205,7 +203,7 @@ static int do_token_out(USBDevice *s, USBPacket *p) } else { /* ignore additional output */ } - return 0; + break; case SETUP_STATE_DATA: if (!(s->setup_buf[0] & USB_DIR_IN)) { @@ -215,23 +213,23 @@ static int do_token_out(USBDevice *s, USBPacket *p) } 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); @@ -249,27 +247,27 @@ static int do_parameter(USBDevice *s, USBPacket *p) 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 @@ -278,30 +276,30 @@ static int do_parameter(USBDevice *s, USBPacket *p) 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; @@ -342,40 +340,57 @@ USBDevice *usb_find_device(USBPort *port, uint8_t addr) 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); @@ -389,32 +404,26 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p) } 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) @@ -422,9 +431,10 @@ 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); @@ -438,7 +448,6 @@ void usb_packet_complete_one(USBDevice *dev, USBPacket *p) 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); @@ -447,7 +456,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *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; } @@ -455,12 +464,11 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p) 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); } } @@ -541,7 +549,8 @@ void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep, uint64_t id, 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; @@ -557,31 +566,31 @@ void usb_packet_addbuf(USBPacket *p, void *ptr, size_t len) 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) diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 1f12eae..b7c3233 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -626,7 +626,8 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len) 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; @@ -696,6 +697,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len ret = len; } memcpy(dest, buf, ret); + p->actual_length = ret; + ret = 0; } return ret; } @@ -715,7 +718,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, 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: @@ -724,7 +727,8 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, * 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); @@ -749,7 +753,8 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, 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: @@ -772,7 +777,8 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, 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); diff --git a/hw/usb/desc.h b/hw/usb/desc.h index 68bb570..ddd3e74 100644 --- a/hw/usb/desc.h +++ b/hw/usb/desc.h @@ -216,7 +216,8 @@ void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str); 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); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 2594c78..b669601 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -503,7 +503,7 @@ static int usb_audio_set_control(USBAudioState *s, uint8_t attrib, 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) { @@ -518,7 +518,7 @@ static int usb_audio_handle_control(USBDevice *dev, USBPacket *p, ret = usb_desc_handle_control(dev, p, request, value, index, length, data); if (ret >= 0) { - return ret; + return; } switch (request) { @@ -534,6 +534,7 @@ static int usb_audio_handle_control(USBDevice *dev, USBPacket *p, } goto fail; } + p->actual_length = ret; break; case ClassInterfaceOutRequest | CR_SET_CUR: @@ -557,10 +558,9 @@ fail: "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, @@ -583,50 +583,35 @@ static void usb_audio_handle_reset(USBDevice *dev) 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) diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 55bc191..bfb96bf 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -285,13 +285,15 @@ static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo, 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); @@ -310,8 +312,6 @@ static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo, fifo->dstart = 0; fifo->dsize = DFIFO_LEN_MASK + 1; } - - return len; } static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s, @@ -363,7 +363,7 @@ static void usb_bt_handle_reset(USBDevice *dev) 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; @@ -382,16 +382,15 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p, 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: @@ -407,16 +406,14 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p, 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; @@ -425,15 +422,15 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p) 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: @@ -460,11 +457,9 @@ static int usb_bt_handle_data(USBDevice *dev, USBPacket *p) default: fail: - ret = USB_RET_STALL; + p->status = USB_RET_STALL; break; } - - return ret; } static void usb_bt_out_hci_packet_event(void *opaque, diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index b3dcd23..55266b1 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -371,7 +371,7 @@ static void usb_hid_handle_reset(USBDevice *dev) 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); @@ -380,10 +380,9 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p, 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: @@ -392,15 +391,15 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p, 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: @@ -409,14 +408,14 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p, 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; } @@ -425,19 +424,18 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p, 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); @@ -445,22 +443,20 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p, 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: @@ -471,15 +467,16 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p) } 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; } @@ -487,10 +484,9 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p) 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) diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 8fd30df..9ee60dd 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -288,7 +288,7 @@ static const char *feature_name(int feature) 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; @@ -298,7 +298,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, ret = usb_desc_handle_control(dev, p, request, value, index, length, data); if (ret >= 0) { - return ret; + return; } switch(request) { @@ -306,7 +306,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, if (value == 0 && index != 0x81) { /* clear ep halt */ goto fail; } - ret = 0; break; /* usb specific requests */ case GetHubStatus: @@ -314,7 +313,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, data[1] = 0; data[2] = 0; data[3] = 0; - ret = 4; + p->actual_length = 4; break; case GetPortStatus: { @@ -331,16 +330,14 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, 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: { @@ -373,7 +370,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, default: goto fail; } - ret = 0; } break; case ClearPortFeature: @@ -413,7 +409,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, default: goto fail; } - ret = 0; } break; case GetHubDescriptor: @@ -437,22 +432,20 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, 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: @@ -465,7 +458,8 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p) 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++) { @@ -478,9 +472,8 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p) 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; @@ -489,10 +482,9 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p) 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) diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index e4a4359..14d9e5a 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1048,7 +1048,7 @@ static void usb_net_handle_reset(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; @@ -1056,10 +1056,9 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p, 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) { @@ -1078,22 +1077,25 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p, } #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]); @@ -1108,72 +1110,67 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p, 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; @@ -1184,21 +1181,23 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p) 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); @@ -1207,24 +1206,21 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p) } 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: @@ -1235,7 +1231,7 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p) 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: @@ -1245,14 +1241,15 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p) 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) diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index a466f99..99b19df 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -219,7 +219,7 @@ static uint8_t usb_get_modem_lines(USBSerialState *s) 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; @@ -228,13 +228,11 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p, 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. */ @@ -323,7 +321,7 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p, 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 */ @@ -338,25 +336,23 @@ static int usb_serial_handle_control(USBDevice *dev, USBPacket *p, 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: @@ -366,6 +362,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p) 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: @@ -374,7 +371,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p) 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; @@ -384,7 +381,6 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p) s->event_trigger &= ~FTDI_BI; header[1] = FTDI_BI; usb_packet_copy(p, header, 2); - ret = 2; break; } else { header[1] = 0; @@ -393,7 +389,7 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p) 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) @@ -404,17 +400,14 @@ static int usb_serial_handle_data(USBDevice *dev, USBPacket *p) 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) diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 1ea0791..190fcd6 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -635,39 +635,38 @@ static void ccid_handle_reset(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) @@ -870,18 +869,13 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv) } } -/* - * 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); @@ -890,7 +884,7 @@ static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p) 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, @@ -949,60 +943,52 @@ static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p) } } 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) { @@ -1010,7 +996,6 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p) 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, @@ -1021,17 +1006,15 @@ static int ccid_handle_data(USBDevice *dev, USBPacket *p) 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) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index e732191..50af971 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -215,7 +215,7 @@ static const USBDesc desc = { 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); @@ -263,7 +263,8 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t 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); } } @@ -292,7 +293,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r 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; } @@ -300,6 +301,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r 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; @@ -330,14 +332,14 @@ static void usb_msd_handle_reset(USBDevice *dev) 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; @@ -345,29 +347,25 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p, 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) @@ -382,11 +380,10 @@ 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; @@ -433,7 +430,6 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) { scsi_req_continue(s->req); } - ret = p->result; break; case USB_MSDM_DATAOUT: @@ -446,7 +442,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) 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; @@ -455,12 +451,10 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) } } } - 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; @@ -481,7 +475,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) } /* Waiting for SCSI write to complete. */ s->packet = p; - ret = USB_RET_ASYNC; + p->status = USB_RET_ASYNC; break; case USB_MSDM_CSW: @@ -493,11 +487,10 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) /* 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; @@ -508,7 +501,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) 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; @@ -517,12 +510,10 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) } } } - 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; @@ -535,11 +526,9 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) 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) diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 4389380..a21b2ba 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -256,10 +256,10 @@ static void usb_uas_send_status_bh(void *opaque) 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); } @@ -349,6 +349,7 @@ static void usb_uas_complete_data_packet(UASRequest *req) 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); } @@ -357,16 +358,16 @@ static void usb_uas_copy_data(UASRequest *req) 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) { @@ -504,17 +505,17 @@ static void usb_uas_handle_reset(USBDevice *dev) } } -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) @@ -641,13 +642,13 @@ incorrect_lun: 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: @@ -656,16 +657,14 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p) 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; @@ -674,11 +673,10 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p) 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; @@ -687,28 +685,26 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p) 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) diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index ed9a5ee..08b416d 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -250,7 +250,7 @@ static void usb_wacom_handle_reset(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; @@ -258,10 +258,9 @@ static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p, 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) { @@ -269,61 +268,58 @@ static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p, 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) diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c index d5c7d46..fe45a1f 100644 --- a/hw/usb/hcd-ehci-pci.c +++ b/hw/usb/hcd-ehci-pci.c @@ -91,6 +91,7 @@ static const VMStateDescription vmstate_ehci_pci = { .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(pcidev, EHCIPCIState), VMSTATE_STRUCT(ehci, EHCIPCIState, 2, vmstate_ehci, EHCIState), + VMSTATE_END_OF_LIST() } }; @@ -105,7 +106,7 @@ static void ehci_class_init(ObjectClass *klass, void *data) k->device_id = i->device_id; k->revision = i->revision; k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_ehci; + dc->vmsd = &vmstate_ehci_pci; dc->props = ehci_pci_properties; } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index d9dc576..ee6c9ae 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -29,9 +29,6 @@ #include "hw/usb/hcd-ehci.h" -/* internal processing - reset HC to try and recover */ -#define USB_RET_PROCERR (-99) - /* Capability Registers Base Address - section 2.2 */ #define CAPLENGTH 0x0000 /* 1-byte, 0x0001 reserved */ #define HCIVERSION 0x0002 /* 2-bytes, i/f version # */ @@ -1111,7 +1108,7 @@ static int ehci_init_transfer(EHCIPacket *p) while (bytes > 0) { if (cpage > 4) { fprintf(stderr, "cpage out of range (%d)\n", cpage); - return USB_RET_PROCERR; + return -1; } page = p->qtd.bufptr[cpage] & QTD_BUFPTR_MASK; @@ -1129,16 +1126,16 @@ static int ehci_init_transfer(EHCIPacket *p) return 0; } -static void ehci_finish_transfer(EHCIQueue *q, int status) +static void ehci_finish_transfer(EHCIQueue *q, int len) { uint32_t cpage, offset; - if (status > 0) { + if (len > 0) { /* update cpage & offset */ cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE); offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK; - offset += status; + offset += len; cpage += offset >> QTD_BUFPTR_SH; offset &= ~QTD_BUFPTR_MASK; @@ -1163,7 +1160,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) 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; @@ -1171,7 +1168,6 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) trace_usb_ehci_packet_action(p->queue, p, "wakeup"); p->async = EHCI_ASYNC_FINISHED; - p->usb_status = packet->result; if (p->queue->async) { qemu_bh_schedule(p->queue->ehci->async_bh); @@ -1181,58 +1177,60 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet) static void ehci_execute_complete(EHCIQueue *q) { EHCIPacket *p = QTAILQ_FIRST(&q->packets); + uint32_t tbytes; assert(p != NULL); assert(p->qtdaddr == q->qtdaddr); assert(p->async == EHCI_ASYNC_INITIALIZED || p->async == EHCI_ASYNC_FINISHED); - DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n", - q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status); + DPRINTF("execute_complete: qhaddr 0x%x, next 0x%x, qtdaddr 0x%x, " + "status %d, actual_length %d\n", + q->qhaddr, q->qh.next, q->qtdaddr, + p->packet.status, p->packet.actual_length); - if (p->usb_status < 0) { - switch (p->usb_status) { - case USB_RET_IOERROR: - case USB_RET_NODEV: - q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR); - set_field(&q->qh.token, 0, QTD_TOKEN_CERR); - ehci_raise_irq(q->ehci, USBSTS_ERRINT); - break; - case USB_RET_STALL: - q->qh.token |= QTD_TOKEN_HALT; - ehci_raise_irq(q->ehci, USBSTS_ERRINT); - break; - case USB_RET_NAK: - set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT); - return; /* We're not done yet with this transaction */ - case USB_RET_BABBLE: - q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE); - ehci_raise_irq(q->ehci, USBSTS_ERRINT); - break; - default: - /* should not be triggerable */ - fprintf(stderr, "USB invalid response %d\n", p->usb_status); - assert(0); - break; + switch (p->packet.status) { + case USB_RET_SUCCESS: + break; + case USB_RET_IOERROR: + case USB_RET_NODEV: + q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR); + set_field(&q->qh.token, 0, QTD_TOKEN_CERR); + ehci_raise_irq(q->ehci, USBSTS_ERRINT); + break; + case USB_RET_STALL: + q->qh.token |= QTD_TOKEN_HALT; + ehci_raise_irq(q->ehci, USBSTS_ERRINT); + break; + case USB_RET_NAK: + set_field(&q->qh.altnext_qtd, 0, QH_ALTNEXT_NAKCNT); + return; /* We're not done yet with this transaction */ + case USB_RET_BABBLE: + q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE); + ehci_raise_irq(q->ehci, USBSTS_ERRINT); + break; + default: + /* should not be triggerable */ + fprintf(stderr, "USB invalid response %d\n", p->packet.status); + assert(0); + break; + } + + /* TODO check 4.12 for splits */ + tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); + if (tbytes && p->pid == USB_TOKEN_IN) { + tbytes -= p->packet.actual_length; + if (tbytes) { + /* 4.15.1.2 must raise int on a short input packet */ + ehci_raise_irq(q->ehci, USBSTS_INT); } } else { - // TODO check 4.12 for splits - uint32_t tbytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); - - if (tbytes && p->pid == USB_TOKEN_IN) { - tbytes -= p->usb_status; - if (tbytes) { - /* 4.15.1.2 must raise int on a short input packet */ - ehci_raise_irq(q->ehci, USBSTS_INT); - } - } else { - tbytes = 0; - } - - DPRINTF("updating tbytes to %d\n", tbytes); - set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES); + tbytes = 0; } - ehci_finish_transfer(q, p->usb_status); + DPRINTF("updating tbytes to %d\n", tbytes); + set_field(&q->qh.token, tbytes, QTD_TOKEN_TBYTES); + + ehci_finish_transfer(q, p->packet.actual_length); usb_packet_unmap(&p->packet, &p->sgl); qemu_sglist_destroy(&p->sgl); p->async = EHCI_ASYNC_NONE; @@ -1248,12 +1246,10 @@ static void ehci_execute_complete(EHCIQueue *q) } } -// 4.10.3 - +/* 4.10.3 returns "again" */ static int ehci_execute(EHCIPacket *p, const char *action) { USBEndpoint *ep; - int ret; int endp; bool spd; @@ -1262,13 +1258,13 @@ static int ehci_execute(EHCIPacket *p, const char *action) if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) { fprintf(stderr, "Attempting to execute inactive qtd\n"); - return USB_RET_PROCERR; + return -1; } if (get_field(p->qtd.token, QTD_TOKEN_TBYTES) > BUFF_SIZE) { ehci_trace_guest_bug(p->queue->ehci, "guest requested more bytes than allowed"); - return USB_RET_PROCERR; + return -1; } p->pid = (p->qtd.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH; @@ -1292,7 +1288,7 @@ static int ehci_execute(EHCIPacket *p, const char *action) if (p->async == EHCI_ASYNC_NONE) { if (ehci_init_transfer(p) != 0) { - return USB_RET_PROCERR; + return -1; } spd = (p->pid == USB_TOKEN_IN && NLPTR_TBIT(p->qtd.altnext) == 0); @@ -1303,17 +1299,18 @@ static int ehci_execute(EHCIPacket *p, const char *action) } 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 -1; } - return ret; + return 1; } /* 4.7.2 @@ -1325,7 +1322,6 @@ static int ehci_process_itd(EHCIState *ehci, { USBDevice *dev; USBEndpoint *ep; - int ret; uint32_t i, len, pid, dir, devaddr, endp; uint32_t pg, off, ptr1, ptr2, max, mult; @@ -1348,7 +1344,7 @@ static int ehci_process_itd(EHCIState *ehci, } if (len > BUFF_SIZE) { - return USB_RET_PROCERR; + return -1; } qemu_sglist_init(&ehci->isgl, 2, ehci->dma); @@ -1370,45 +1366,45 @@ static int ehci_process_itd(EHCIState *ehci, 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); } else { DPRINTF("ISOCH: attempt to addess non-iso endpoint\n"); - ret = USB_RET_NAK; + ehci->ipacket.status = USB_RET_NAK; + ehci->ipacket.actual_length = 0; } qemu_sglist_destroy(&ehci->isgl); - if (ret < 0) { - switch (ret) { - default: - fprintf(stderr, "Unexpected iso usb result: %d\n", ret); - /* Fall through */ - case USB_RET_IOERROR: - case USB_RET_NODEV: - /* 3.3.2: XACTERR is only allowed on IN transactions */ - if (dir) { - itd->transact[i] |= ITD_XACT_XACTERR; - ehci_raise_irq(ehci, USBSTS_ERRINT); - } - break; - case USB_RET_BABBLE: - itd->transact[i] |= ITD_XACT_BABBLE; + switch (ehci->ipacket.status) { + case USB_RET_SUCCESS: + break; + default: + fprintf(stderr, "Unexpected iso usb result: %d\n", + ehci->ipacket.status); + /* Fall through */ + case USB_RET_IOERROR: + case USB_RET_NODEV: + /* 3.3.2: XACTERR is only allowed on IN transactions */ + if (dir) { + itd->transact[i] |= ITD_XACT_XACTERR; ehci_raise_irq(ehci, USBSTS_ERRINT); - break; - case USB_RET_NAK: - /* no data for us, so do a zero-length transfer */ - ret = 0; - break; } + break; + case USB_RET_BABBLE: + itd->transact[i] |= ITD_XACT_BABBLE; + ehci_raise_irq(ehci, USBSTS_ERRINT); + break; + case USB_RET_NAK: + /* no data for us, so do a zero-length transfer */ + ehci->ipacket.actual_length = 0; + break; } - if (ret >= 0) { - if (!dir) { - /* OUT */ - set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH); - } else { - /* IN */ - set_field(&itd->transact[i], ret, ITD_XACT_LENGTH); - } + if (!dir) { + set_field(&itd->transact[i], len - ehci->ipacket.actual_length, + ITD_XACT_LENGTH); /* OUT */ + } else { + set_field(&itd->transact[i], ehci->ipacket.actual_length, + ITD_XACT_LENGTH); /* IN */ } if (itd->transact[i] & ITD_XACT_IOC) { ehci_raise_irq(ehci, USBSTS_INT); @@ -1746,8 +1742,7 @@ static int ehci_state_fetchqtd(EHCIQueue *q) break; case EHCI_ASYNC_INFLIGHT: /* Check if the guest has added new tds to the queue */ - again = (ehci_fill_queue(QTAILQ_LAST(&q->packets, pkts_head)) == - USB_RET_PROCERR) ? -1 : 1; + again = ehci_fill_queue(QTAILQ_LAST(&q->packets, pkts_head)); /* Unfinished async handled packet, go horizontal */ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); break; @@ -1784,6 +1779,7 @@ static int ehci_state_horizqh(EHCIQueue *q) return again; } +/* Returns "again" */ static int ehci_fill_queue(EHCIPacket *p) { USBEndpoint *ep = p->packet.ep; @@ -1812,17 +1808,14 @@ static int ehci_fill_queue(EHCIPacket *p) p = ehci_alloc_packet(q); p->qtdaddr = qtdaddr; p->qtd = qtd; - p->usb_status = ehci_execute(p, "queue"); - if (p->usb_status == USB_RET_PROCERR) { - break; + if (ehci_execute(p, "queue") == -1) { + return -1; } - assert(p->usb_status == USB_RET_ASYNC); + assert(p->packet.status == USB_RET_ASYNC); p->async = EHCI_ASYNC_INFLIGHT; } - if (p->usb_status != USB_RET_PROCERR) { - usb_device_flush_ep_queue(ep->dev, ep); - } - return p->usb_status; + usb_device_flush_ep_queue(ep->dev, ep); + return 1; } static int ehci_state_execute(EHCIQueue *q) @@ -1851,18 +1844,17 @@ static int ehci_state_execute(EHCIQueue *q) ehci_set_usbsts(q->ehci, USBSTS_REC); } - p->usb_status = ehci_execute(p, "process"); - if (p->usb_status == USB_RET_PROCERR) { - again = -1; + again = ehci_execute(p, "process"); + if (again == -1) { goto out; } - if (p->usb_status == USB_RET_ASYNC) { + if (p->packet.status == USB_RET_ASYNC) { ehci_flush_qh(q); trace_usb_ehci_packet_action(p->queue, p, "async"); p->async = EHCI_ASYNC_INFLIGHT; ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); if (q->async) { - again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1; + again = ehci_fill_queue(p); } else { again = 1; } @@ -1891,7 +1883,7 @@ static int ehci_state_executing(EHCIQueue *q) } /* 4.10.5 */ - if (p->usb_status == USB_RET_NAK) { + if (p->packet.status == USB_RET_NAK) { ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH); } else { ehci_set_state(q->ehci, q->async, EST_WRITEBACK); diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 0ec675c..d8078f4 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -230,7 +230,6 @@ struct EHCIPacket { QEMUSGList sgl; int pid; enum async_state async; - int usb_status; }; struct EHCIQueue { diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c index 4f55390..c707f7a 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -607,7 +607,6 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep, { USBDevice *dev; USBEndpoint *uep; - int ret; int idx = epnum && dir; int ttype; @@ -632,15 +631,19 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep, 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); } @@ -754,7 +757,6 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque) if (ep->status[1] == USB_RET_STALL) { ep->status[1] = 0; - packey->result = 0; ep->csr[1] |= MGC_M_RXCSR_H_RXSTALL; if (!epnum) @@ -793,14 +795,12 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque) /* 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 */ } diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 7571e9e..6a39e96 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -807,21 +807,24 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, 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", @@ -997,7 +1000,6 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) } #endif if (completion) { - ret = ohci->usb_packet.result; ohci->async_td = 0; ohci->async_complete = 0; } else { @@ -1017,16 +1019,22 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) 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, diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index f4b555a..2838d21 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -780,22 +780,21 @@ static int uhci_handle_td_error(UHCIState *s, UHCI_TD *td, uint32_t td_addr, 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 @@ -824,7 +823,7 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ 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; @@ -915,13 +914,14 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, 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: @@ -932,8 +932,8 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, 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); @@ -941,13 +941,11 @@ static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr, 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) @@ -955,7 +953,7 @@ 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; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 900abf5..8ef4b07 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -634,6 +634,34 @@ static inline dma_addr_t xhci_mask64(uint64_t addr) } } +static inline void xhci_dma_read_u32s(XHCIState *xhci, dma_addr_t addr, + uint32_t *buf, size_t len) +{ + int i; + + assert((len % sizeof(uint32_t)) == 0); + + pci_dma_read(&xhci->pci_dev, addr, buf, len); + + for (i = 0; i < (len / sizeof(uint32_t)); i++) { + buf[i] = le32_to_cpu(buf[i]); + } +} + +static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr, + uint32_t *buf, size_t len) +{ + int i; + uint32_t tmp[len / sizeof(uint32_t)]; + + assert((len % sizeof(uint32_t)) == 0); + + for (i = 0; i < (len / sizeof(uint32_t)); i++) { + tmp[i] = cpu_to_le32(buf[i]); + } + pci_dma_write(&xhci->pci_dev, addr, tmp, len); +} + static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport) { int index; @@ -1045,14 +1073,14 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, { uint32_t ctx[5]; - pci_dma_read(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx)); + xhci_dma_read_u32s(xhci, epctx->pctx, ctx, sizeof(ctx)); ctx[0] &= ~EP_STATE_MASK; ctx[0] |= state; ctx[2] = epctx->ring.dequeue | epctx->ring.ccs; ctx[3] = (epctx->ring.dequeue >> 16) >> 16; DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n", epctx->pctx, state, ctx[3], ctx[2]); - pci_dma_write(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx)); + xhci_dma_write_u32s(xhci, epctx->pctx, ctx, sizeof(ctx)); epctx->state = state; } @@ -1388,7 +1416,7 @@ static void xhci_xfer_report(XHCITransfer *xfer) XHCIState *xhci = xfer->xhci; int i; - left = xfer->packet.result < 0 ? 0 : xfer->packet.result; + left = xfer->packet.actual_length; for (i = 0; i < xfer->trb_count; i++) { XHCITRB *trb = &xfer->trbs[i]; @@ -1416,7 +1444,7 @@ static void xhci_xfer_report(XHCITransfer *xfer) if (!reported && ((trb->control & TRB_TR_IOC) || (shortpkt && (trb->control & TRB_TR_ISP)) || - (xfer->status != CC_SUCCESS))) { + (xfer->status != CC_SUCCESS && left == 0))) { event.slotid = xfer->slotid; event.epid = xfer->epid; event.length = (trb->status & 0x1ffff) - chunk; @@ -1490,16 +1518,16 @@ static int xhci_setup_packet(XHCITransfer *xfer) 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; @@ -1513,16 +1541,16 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret) 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); @@ -1534,7 +1562,8 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret) 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; @@ -1544,7 +1573,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) { XHCITRB *trb_setup, *trb_status; uint8_t bmRequestType; - int ret; trb_setup = &xfer->trbs[0]; trb_status = &xfer->trbs[xfer->trb_count-1]; @@ -1587,9 +1615,9 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) } 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); } @@ -1636,7 +1664,6 @@ static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer, 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); @@ -1671,9 +1698,9 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx 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); } @@ -1711,7 +1738,6 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid if (epctx->retry) { XHCITransfer *xfer = epctx->retry; - int result; trace_usb_xhci_xfer_retry(xfer); assert(xfer->running_retry); @@ -1725,19 +1751,19 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid 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; @@ -1883,14 +1909,14 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, assert(slotid >= 1 && slotid <= xhci->numslots); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); - pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx)); + poctx = ldq_le_pci_dma(&xhci->pci_dev, dcbaap + 8*slotid); ictx = xhci_mask64(pictx); - octx = xhci_mask64(le64_to_cpu(poctx)); + octx = xhci_mask64(poctx); DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx); DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); - pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); + xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx)); if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -1898,8 +1924,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, return CC_TRB_ERROR; } - pci_dma_read(&xhci->pci_dev, ictx+32, slot_ctx, sizeof(slot_ctx)); - pci_dma_read(&xhci->pci_dev, ictx+64, ep0_ctx, sizeof(ep0_ctx)); + xhci_dma_read_u32s(xhci, ictx+32, slot_ctx, sizeof(slot_ctx)); + xhci_dma_read_u32s(xhci, ictx+64, ep0_ctx, sizeof(ep0_ctx)); DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); @@ -1953,8 +1979,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n", ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]); - pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); - pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); + xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_write_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx)); return res; } @@ -1987,17 +2013,17 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, } } - pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT); slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT; DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } - pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); + xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx)); if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -2005,8 +2031,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, return CC_TRB_ERROR; } - pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx)); - pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_read_u32s(xhci, ictx+32, islot_ctx, sizeof(islot_ctx)); + xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) { fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]); @@ -2018,8 +2044,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, xhci_disable_ep(xhci, slotid, i); } if (ictl_ctx[1] & (1<<i)) { - pci_dma_read(&xhci->pci_dev, ictx+32+(32*i), ep_ctx, - sizeof(ep_ctx)); + xhci_dma_read_u32s(xhci, ictx+32+(32*i), ep_ctx, sizeof(ep_ctx)); DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n", i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2], ep_ctx[3], ep_ctx[4]); @@ -2031,7 +2056,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n", i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2], ep_ctx[3], ep_ctx[4]); - pci_dma_write(&xhci->pci_dev, octx+(32*i), ep_ctx, sizeof(ep_ctx)); + xhci_dma_write_u32s(xhci, octx+(32*i), ep_ctx, sizeof(ep_ctx)); } } @@ -2043,7 +2068,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } @@ -2068,7 +2093,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx); DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); - pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); + xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx)); if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -2077,12 +2102,12 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, } if (ictl_ctx[1] & 0x1) { - pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx)); + xhci_dma_read_u32s(xhci, ictx+32, islot_ctx, sizeof(islot_ctx)); DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n", islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]); - pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); slot_ctx[1] &= ~0xFFFF; /* max exit latency */ slot_ctx[1] |= islot_ctx[1] & 0xFFFF; @@ -2092,17 +2117,17 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); } if (ictl_ctx[1] & 0x2) { - pci_dma_read(&xhci->pci_dev, ictx+64, iep0_ctx, sizeof(iep0_ctx)); + xhci_dma_read_u32s(xhci, ictx+64, iep0_ctx, sizeof(iep0_ctx)); DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n", iep0_ctx[0], iep0_ctx[1], iep0_ctx[2], iep0_ctx[3], iep0_ctx[4]); - pci_dma_read(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); + xhci_dma_read_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx)); ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/ ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000; @@ -2110,7 +2135,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n", ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]); - pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); + xhci_dma_write_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx)); } return CC_SUCCESS; @@ -2135,12 +2160,12 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid) } } - pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT); slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT; DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } @@ -2922,11 +2947,11 @@ static void xhci_complete(USBPort *port, USBPacket *packet) { 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); } diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c index ec26266..6473e8b 100644 --- a/hw/usb/host-bsd.c +++ b/hw/usb/host-bsd.c @@ -121,7 +121,7 @@ static void usb_host_handle_reset(USBDevice *dev) * -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, @@ -139,7 +139,6 @@ static int usb_host_handle_control(USBDevice *dev, /* specific SET_ADDRESS support */ dev->addr = value; - return 0; } else if ((request >> 8) == UT_WRITE_DEVICE && (request & 0xff) == UR_SET_CONFIG) { @@ -151,10 +150,8 @@ static int usb_host_handle_control(USBDevice *dev, 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) { @@ -168,10 +165,8 @@ static int usb_host_handle_control(USBDevice *dev, 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; @@ -201,14 +196,14 @@ static int usb_host_handle_control(USBDevice *dev, 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; @@ -232,7 +227,8 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) 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) { @@ -267,12 +263,13 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) 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; } } diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 3a258b4..ca3e24a 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -366,28 +366,29 @@ static void async_complete(void *opaque) 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); } } @@ -733,27 +734,31 @@ static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep) 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) { @@ -766,18 +771,17 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in) 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; @@ -792,7 +796,8 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in) /* 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 */ @@ -823,17 +828,16 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in) /* (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; @@ -843,11 +847,9 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in) } } } - - 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; @@ -862,7 +864,8 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) 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) { @@ -877,13 +880,15 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) 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; @@ -933,17 +938,19 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) 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) @@ -955,14 +962,13 @@ 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; @@ -987,14 +993,15 @@ again: } 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; @@ -1011,7 +1018,8 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt) } if (iface >= USB_MAX_INTERFACES) { - return USB_RET_STALL; + p->status = USB_RET_STALL; + return; } si.interface = iface; @@ -1022,15 +1030,15 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt) 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); @@ -1048,19 +1056,19 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, 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 */ @@ -1068,17 +1076,16 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, 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); @@ -1112,14 +1119,17 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, 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 */ diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index c5cfe0b..be9a232 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -141,8 +141,8 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id, 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 @@ -443,7 +443,7 @@ static void usbredir_handle_reset(USBDevice *udev) 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; @@ -500,7 +500,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, !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; } @@ -514,27 +514,23 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, /* 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; - } - len = isop->len; if (len > p->iov.size) { 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; + len = p->iov.size; + status = usb_redir_babble; } usb_packet_copy(p, isop->data, len); bufp_free(dev, isop, ep); - return len; + usbredir_handle_status(dev, p, status); } else { /* If the stream was not started because of a pending error don't send the packet to the usb-host */ @@ -554,7 +550,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p, 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); } } @@ -572,7 +568,7 @@ static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep) 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; @@ -581,7 +577,8 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, 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; @@ -608,10 +605,10 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p, &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) { @@ -643,28 +640,25 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev, 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); - } - 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; + len = p->iov.size; + status = usb_redir_babble; } usb_packet_copy(p, intp->data, len); bufp_free(dev, intp, ep); - return len; + usbredir_handle_status(dev, p, status); } else { /* Output interrupt endpoint, normal async operation */ struct usb_redir_interrupt_packet_header interrupt_packet; @@ -674,7 +668,8 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev, 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; @@ -685,7 +680,7 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev, 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; } } @@ -705,7 +700,7 @@ static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev, 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; @@ -718,21 +713,26 @@ static int usbredir_handle_data(USBDevice *udev, USBPacket *p) 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; } } @@ -743,7 +743,7 @@ static void usbredir_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) } } -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; @@ -768,19 +768,19 @@ static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p, 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; @@ -808,10 +808,10 @@ static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p, 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; @@ -821,17 +821,18 @@ static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p, 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 */ @@ -839,15 +840,19 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, 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 */ @@ -871,7 +876,7 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p, &control_packet, data, length); } usbredirparser_do_write(dev->parser); - return USB_RET_ASYNC; + p->status = USB_RET_ASYNC; } /* @@ -1159,29 +1164,34 @@ error: * 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; } } @@ -1412,7 +1422,6 @@ static void usbredir_configuration_status(void *priv, uint64_t id, { 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); @@ -1421,9 +1430,9 @@ static void usbredir_configuration_status(void *priv, uint64_t 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); } } @@ -1433,7 +1442,6 @@ static void usbredir_alt_setting_status(void *priv, uint64_t id, { 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, @@ -1443,10 +1451,9 @@ static void usbredir_alt_setting_status(void *priv, uint64_t id, 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); } } @@ -1522,18 +1529,18 @@ static void usbredir_control_packet(void *priv, uint64_t id, 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 (data_len > 0) { 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 { + if (data_len > sizeof(dev->dev.data_buf)) { ERROR("ctrl buffer too small (%d > %zu)\n", data_len, sizeof(dev->dev.data_buf)); - len = USB_RET_STALL; + p->status = USB_RET_STALL; + data_len = len = sizeof(dev->dev.data_buf); } + memcpy(dev->dev.data_buf, data, data_len); } - p->result = len; + p->actual_length = len; usb_generic_async_ctrl_complete(&dev->dev, p); } free(data); @@ -1554,23 +1561,23 @@ static void usbredir_bulk_packet(void *priv, uint64_t id, 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 (data_len > 0) { usbredir_log_data(dev, "bulk data in:", data, data_len); - if (data_len <= size) { - if (p->combined) { - iov_from_buf(p->combined->iov.iov, p->combined->iov.niov, - 0, data, data_len); - } else { - usb_packet_copy(p, data, data_len); - } - } else { + if (data_len > size) { ERROR("bulk got more data then requested (%d > %zd)\n", data_len, p->iov.size); - len = USB_RET_BABBLE; + p->status = USB_RET_BABBLE; + data_len = len = size; + } + if (p->combined) { + iov_from_buf(p->combined->iov.iov, p->combined->iov.niov, + 0, data, data_len); + } else { + usb_packet_copy(p, data, data_len); } } - 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 { @@ -1632,12 +1639,10 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id, /* bufp_alloc also adds the packet to the ep queue */ bufp_alloc(dev, data, data_len, interrupt_packet->status, ep); } else { - int len = interrupt_packet->length; - 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 = interrupt_packet->length; usb_packet_complete(&dev->dev, p); } } |