diff --git a/hw/usb.h b/hw/usb.h
index 3c8ba01..7b7a988 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -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)
@@ -362,7 +363,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;
diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c
index ab23ade..f725d50 100644
--- a/hw/usb/combined-packet.c
+++ b/hw/usb/combined-packet.c
@@ -46,7 +46,7 @@ void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p)
     USBEndpoint *ep = p->ep;
     USBPacket *next;
     enum { completing, complete, leftover };
-    int result, state = completing;
+    int status, actual_length, state = completing;
     bool short_not_ok;
 
     if (combined == NULL) {
@@ -56,27 +56,34 @@ 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) {
             /* Distribute data over uncombined packets */
-            if (result >= p->iov.size) {
-                p->result = p->iov.size;
+            if (actual_length >= p->iov.size) {
+                p->actual_length = p->iov.size;
             } else {
                 /* Send short or error packet to complete the transfer */
-                p->result = result;
+                p->actual_length = actual_length;
                 state = complete;
             }
+            /* Report status on the last packet */
+            if (state == complete || next == NULL) {
+                p->status = status;
+            } else {
+                p->status = USB_RET_SUCCESS;
+            }
             p->short_not_ok = short_not_ok;
             usb_combined_packet_remove(combined, p);
             usb_packet_complete_one(dev, p);
-            result -= p->result;
+            actual_length -= p->actual_length;
         } else {
             /* Remove any leftover packets from the queue */
             state = leftover;
-            p->result = USB_RET_REMOVE_FROM_QUEUE;
+            p->status = USB_RET_REMOVE_FROM_QUEUE;
             dev->port->ops->complete(dev->port, p);
         }
     }
@@ -129,7 +136,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;
         }
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 99b9fdb..34a65af 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -100,14 +100,14 @@ void usb_wakeup(USBEndpoint *ep)
 static int do_token_setup(USBDevice *s, USBPacket *p)
 {
     int request, value, index;
-    int ret = 0;
+    int ret = USB_RET_SUCCESS;
 
     if (p->iov.size != 8) {
         return USB_RET_STALL;
     }
 
     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;
 
@@ -122,11 +122,13 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
              s->setup_state = SETUP_STATE_SETUP;
              return USB_RET_ASYNC;
         }
-        if (ret < 0)
+        if (ret != USB_RET_SUCCESS) {
             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)) {
@@ -141,13 +143,14 @@ static int do_token_setup(USBDevice *s, USBPacket *p)
             s->setup_state = SETUP_STATE_DATA;
     }
 
+    p->actual_length = 8;
     return ret;
 }
 
 static int do_token_in(USBDevice *s, USBPacket *p)
 {
     int request, value, index;
-    int ret = 0;
+    int ret;
 
     assert(p->ep->nr == 0);
 
@@ -164,13 +167,12 @@ static int do_token_in(USBDevice *s, USBPacket *p)
                 return USB_RET_ASYNC;
             }
             s->setup_state = SETUP_STATE_IDLE;
-            if (ret > 0)
-                return 0;
+            p->actual_length = 0;
             return ret;
         }
 
         /* return 0 byte */
-        return 0;
+        return USB_RET_SUCCESS;
 
     case SETUP_STATE_DATA:
         if (s->setup_buf[0] & USB_DIR_IN) {
@@ -182,7 +184,7 @@ static int do_token_in(USBDevice *s, USBPacket *p)
             s->setup_index += len;
             if (s->setup_index >= s->setup_len)
                 s->setup_state = SETUP_STATE_ACK;
-            return len;
+            return USB_RET_SUCCESS;
         }
 
         s->setup_state = SETUP_STATE_IDLE;
@@ -205,7 +207,7 @@ static int do_token_out(USBDevice *s, USBPacket *p)
         } else {
             /* ignore additional output */
         }
-        return 0;
+        return USB_RET_SUCCESS;
 
     case SETUP_STATE_DATA:
         if (!(s->setup_buf[0] & USB_DIR_IN)) {
@@ -217,7 +219,7 @@ static int do_token_out(USBDevice *s, USBPacket *p)
             s->setup_index += len;
             if (s->setup_index >= s->setup_len)
                 s->setup_state = SETUP_STATE_ACK;
-            return len;
+            return USB_RET_SUCCESS;
         }
 
         s->setup_state = SETUP_STATE_IDLE;
@@ -231,7 +233,7 @@ static int do_token_out(USBDevice *s, USBPacket *p)
 static int do_parameter(USBDevice *s, USBPacket *p)
 {
     int request, value, index;
-    int i, ret = 0;
+    int i, ret;
 
     for (i = 0; i < 8; i++) {
         s->setup_buf[i] = p->parameter >> (i*8);
@@ -258,14 +260,15 @@ static int do_parameter(USBDevice *s, USBPacket *p)
 
     ret = usb_device_handle_control(s, p, request, value, index,
                                     s->setup_len, s->data_buf);
-    if (ret < 0) {
-        return ret;
+    if (ret == USB_RET_ASYNC) {
+        return USB_RET_ASYNC;
     }
 
-    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);
     }
 
@@ -278,30 +281,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;
@@ -404,7 +407,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
              */
             assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue));
             if (ret != USB_RET_NAK) {
-                p->result = ret;
+                p->status = ret;
                 usb_packet_set_state(p, USB_PACKET_COMPLETE);
             }
         }
@@ -421,9 +424,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);
@@ -446,7 +450,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;
         }
@@ -459,7 +463,7 @@ void usb_packet_complete(USBDevice *dev, USBPacket *p)
             usb_packet_set_state(p, USB_PACKET_ASYNC);
             break;
         }
-        p->result = ret;
+        p->status = ret;
         usb_packet_complete_one(ep->dev, p);
     }
 }
@@ -540,7 +544,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;
@@ -556,31 +561,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..b22a8e8 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -434,7 +434,7 @@ static int usb_desc_set_interface(USBDevice *dev, int index, int value)
     if (old != value) {
         usb_device_set_interface(dev, index, old, value);
     }
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int usb_desc_set_config(USBDevice *dev, int value)
@@ -467,7 +467,7 @@ static int usb_desc_set_config(USBDevice *dev, int value)
         dev->ifaces[i] = NULL;
     }
 
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static void usb_desc_setdefaults(USBDevice *dev)
@@ -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 = USB_RET_SUCCESS;
     }
     return ret;
 }
@@ -711,11 +714,11 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
         dev->addr = value;
         trace_usb_set_addr(dev->addr);
-        ret = 0;
+        ret = USB_RET_SUCCESS;
         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 = USB_RET_SUCCESS;
         break;
     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
         ret = usb_desc_set_config(dev, value);
@@ -749,20 +753,21 @@ 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 = USB_RET_SUCCESS;
         break;
     }
     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
         if (value == USB_DEVICE_REMOTE_WAKEUP) {
             dev->remote_wakeup = 0;
-            ret = 0;
+            ret = USB_RET_SUCCESS;
         }
         trace_usb_clear_device_feature(dev->addr, value, ret);
         break;
     case DeviceOutRequest | USB_REQ_SET_FEATURE:
         if (value == USB_DEVICE_REMOTE_WAKEUP) {
             dev->remote_wakeup = 1;
-            ret = 0;
+            ret = USB_RET_SUCCESS;
         }
         trace_usb_set_device_feature(dev->addr, value, ret);
         break;
@@ -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 = USB_RET_SUCCESS;
         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..16771ab 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -517,7 +517,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) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
 
@@ -534,6 +534,8 @@ static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
             }
             goto fail;
         }
+        p->actual_length = ret;
+        ret = USB_RET_SUCCESS;
         break;
 
     case ClassInterfaceOutRequest | CR_SET_CUR:
@@ -548,6 +550,7 @@ static int usb_audio_handle_control(USBDevice *dev, USBPacket *p,
             }
             goto fail;
         }
+        ret = USB_RET_SUCCESS;
         break;
 
     default:
@@ -597,7 +600,7 @@ static int usb_audio_handle_dataout(USBAudioState *s, USBPacket *p)
                 p->iov.size - rc);
     }
 
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int usb_audio_handle_data(USBDevice *dev, USBPacket *p)
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index 55bc191..dadfc66 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -311,7 +311,7 @@ static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
         fifo->dsize = DFIFO_LEN_MASK + 1;
     }
 
-    return len;
+    return USB_RET_SUCCESS;
 }
 
 static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s,
@@ -370,7 +370,7 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
     int ret;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
+    if (ret == USB_RET_SUCCESS) {
         switch (request) {
         case DeviceRequest | USB_REQ_GET_CONFIGURATION:
             s->config = 0;
@@ -385,13 +385,13 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
         return ret;
     }
 
-    ret = 0;
+    ret = USB_RET_SUCCESS;
     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:
@@ -416,7 +416,7 @@ static int usb_bt_handle_control(USBDevice *dev, USBPacket *p,
 static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
 {
     struct USBBtState *s = (struct USBBtState *) dev->opaque;
-    int ret = 0;
+    int ret = USB_RET_SUCCESS;
 
     if (!s->config)
         goto fail;
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index b3dcd23..c7f2dcf 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -379,11 +379,11 @@ static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
     int ret;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
 
-    ret = 0;
+    ret = USB_RET_SUCCESS;
     switch (request) {
         /* hid specific requests */
     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
@@ -392,15 +392,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 +409,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 +425,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,7 +444,6 @@ 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:
@@ -460,7 +458,7 @@ static int 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, ret = USB_RET_SUCCESS;
 
     switch (p->pid) {
     case USB_TOKEN_IN:
@@ -475,11 +473,11 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
             }
             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;
         }
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 8fd30df..eb2ce60 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -297,7 +297,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
     trace_usb_hub_control(s->dev.addr, request, value, index, length);
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
 
@@ -306,7 +306,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
         if (value == 0 && index != 0x81) { /* clear ep halt */
             goto fail;
         }
-        ret = 0;
+        ret = USB_RET_SUCCESS;
         break;
         /* usb specific requests */
     case GetHubStatus:
@@ -314,7 +314,8 @@ 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;
+        ret = USB_RET_SUCCESS;
         break;
     case GetPortStatus:
         {
@@ -331,16 +332,17 @@ 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;
+            ret = USB_RET_SUCCESS;
         }
         break;
     case SetHubFeature:
     case ClearHubFeature:
         if (value == 0 || value == 1) {
+            ret = USB_RET_SUCCESS;
         } else {
             goto fail;
         }
-        ret = 0;
         break;
     case SetPortFeature:
         {
@@ -373,7 +375,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
             default:
                 goto fail;
             }
-            ret = 0;
+            ret = USB_RET_SUCCESS;
         }
         break;
     case ClearPortFeature:
@@ -413,7 +415,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
             default:
                 goto fail;
             }
-            ret = 0;
+            ret = USB_RET_SUCCESS;
         }
         break;
     case GetHubDescriptor:
@@ -437,8 +439,9 @@ 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;
+            ret = USB_RET_SUCCESS;
             break;
         }
     default:
@@ -478,7 +481,7 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
                     buf[i] = status >> (8 * i);
                 }
                 usb_packet_copy(p, buf, n);
-                ret = n;
+                ret = USB_RET_SUCCESS;
             } else {
                 ret = USB_RET_NAK; /* usb11 11.13.1 */
             }
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index c84892c..7fa5452 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -889,7 +889,7 @@ static int rndis_init_response(USBNetState *s, rndis_init_msg_type *buf)
     resp->PacketAlignmentFactor = cpu_to_le32(0);
     resp->AFListOffset = cpu_to_le32(0);
     resp->AFListSize = cpu_to_le32(0);
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int rndis_query_response(USBNetState *s,
@@ -925,7 +925,7 @@ static int rndis_query_response(USBNetState *s,
         resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
         resp->InformationBufferLength = cpu_to_le32(0);
         resp->InformationBufferOffset = cpu_to_le32(0);
-        return 0;
+        return USB_RET_SUCCESS;
     }
 
     resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
@@ -934,7 +934,7 @@ static int rndis_query_response(USBNetState *s,
     resp->InformationBufferLength = cpu_to_le32(infobuflen);
     memcpy(resp + 1, infobuf, infobuflen);
 
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int rndis_set_response(USBNetState *s,
@@ -961,11 +961,11 @@ static int rndis_set_response(USBNetState *s,
     if (ret < 0) {
         /* OID not supported */
         resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
-        return 0;
+        return USB_RET_SUCCESS;
     }
     resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int rndis_reset_response(USBNetState *s, rndis_reset_msg_type *buf)
@@ -981,7 +981,7 @@ static int rndis_reset_response(USBNetState *s, rndis_reset_msg_type *buf)
     resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
     resp->AddressingReset = cpu_to_le32(1); /* reset information */
 
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int rndis_keepalive_response(USBNetState *s,
@@ -998,7 +998,7 @@ static int rndis_keepalive_response(USBNetState *s,
     resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
     resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
 
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int rndis_parse(USBNetState *s, uint8_t *data, int length)
@@ -1015,7 +1015,7 @@ static int rndis_parse(USBNetState *s, uint8_t *data, int length)
 
     case RNDIS_HALT_MSG:
         s->rndis_state = RNDIS_UNINITIALIZED;
-        return 0;
+        return USB_RET_SUCCESS;
 
     case RNDIS_QUERY_MSG:
         return rndis_query_response(s, (rndis_query_msg_type *) data, length);
@@ -1047,11 +1047,11 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
     int ret;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
 
-    ret = 0;
+    ret = USB_RET_SUCCESS;
     switch(request) {
     case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
         if (!is_rndis(s) || value || index != 0) {
@@ -1076,16 +1076,16 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
         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]);
@@ -1109,7 +1109,7 @@ static int usb_net_handle_control(USBDevice *dev, USBPacket *p,
 static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
 {
     le32 buf[2];
-    int ret = 8;
+    int ret = USB_RET_SUCCESS;
 
     if (p->iov.size < 8) {
         return USB_RET_STALL;
@@ -1132,40 +1132,37 @@ static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
 
 static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
 {
-    int ret = USB_RET_NAK;
+    int len;
 
     if (s->in_ptr > s->in_len) {
         s->in_ptr = s->in_len = 0;
-        ret = USB_RET_NAK;
-        return ret;
+        return USB_RET_NAK;
     }
     if (!s->in_len) {
-        ret = USB_RET_NAK;
-        return ret;
+        return USB_RET_NAK;
     }
-    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 */
         s->in_ptr = s->in_len = 0;
     }
 
 #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;
+    return USB_RET_SUCCESS;
 }
 
 static int 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;
@@ -1176,21 +1173,22 @@ 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 USB_RET_SUCCESS;
     }
     len = le32_to_cpu(msg->MessageLength);
     if (s->out_ptr < 8 || s->out_ptr < len)
-        return ret;
+        return USB_RET_SUCCESS;
     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);
@@ -1200,7 +1198,7 @@ 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;
+    return USB_RET_SUCCESS;
 }
 
 static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 0ddfab6..c44e5a9 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -227,14 +227,13 @@ 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) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
 
-    ret = 0;
+    ret = USB_RET_SUCCESS;
     switch (request) {
     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-        ret = 0;
         break;
 
         /* Class specific requests.  */
@@ -323,7 +322,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,7 +337,7 @@ 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:
@@ -366,6 +365,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:
@@ -384,7 +384,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;
@@ -404,7 +403,6 @@ 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:
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 1ea0791..86c8b3f 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -639,11 +639,11 @@ static int 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) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
 
@@ -890,7 +890,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 USB_RET_SUCCESS;
     }
     if (s->bulk_out_pos < 10) {
         DPRINTF(s, 1,
@@ -949,45 +949,45 @@ static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
         }
     }
     s->bulk_out_pos = 0;
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int 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;
+        return 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;
+    return USB_RET_SUCCESS;
 }
 
 static int ccid_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
-    int ret = 0;
+    int ret = USB_RET_SUCCESS;
     uint8_t buf[2];
 
     switch (p->pid) {
@@ -1010,7 +1010,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,
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index e732191..70dae03 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,7 @@ 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) {
             usb_msd_packet_complete(s);
         }
     }
@@ -292,7 +292,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;
             }
@@ -330,7 +330,7 @@ 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);
     }
 
@@ -344,24 +344,22 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
     int ret;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
 
-    ret = 0;
+    ret = USB_RET_SUCCESS;
     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;
@@ -386,7 +384,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
 {
     MSDState *s = (MSDState *)dev;
     uint32_t tag;
-    int ret = 0;
+    int ret = USB_RET_SUCCESS;
     struct usb_msd_cbw cbw;
     uint8_t devep = p->ep->nr;
 
@@ -433,7 +431,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 +443,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 +452,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;
             }
             break;
 
@@ -497,7 +492,6 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             } else {
                 usb_msd_send_status(s, p);
                 s->mode = USB_MSDM_CBW;
-                ret = 13;
             }
             break;
 
@@ -508,7 +502,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 +511,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;
             }
             break;
 
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 5a0057a..8014c2b 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -256,7 +256,6 @@ 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);
 
@@ -357,16 +356,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) {
@@ -510,7 +509,7 @@ static int usb_uas_handle_control(USBDevice *dev, USBPacket *p,
     int ret;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
     fprintf(stderr, "%s: unhandled control request\n", __func__);
@@ -649,7 +648,7 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
     uas_ui ui;
     UASStatus *st;
     UASRequest *req;
-    int length, ret = 0;
+    int length, ret = USB_RET_SUCCESS;
 
     switch (p->ep->nr) {
     case UAS_PIPE_ID_COMMAND:
@@ -658,15 +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);
+            p->actual_length = 0;
             ret = USB_RET_STALL;
             break;
         }
@@ -680,7 +678,6 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
             break;
         }
         usb_packet_copy(p, &st->status, st->length);
-        ret = st->length;
         QTAILQ_REMOVE(&uas->results, st, next);
         g_free(st);
         break;
@@ -695,9 +692,8 @@ static int usb_uas_handle_data(USBDevice *dev, USBPacket *p)
         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;
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index ed9a5ee..3945948 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -257,11 +257,11 @@ static int usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
     int ret;
 
     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
-    if (ret >= 0) {
+    if (ret == USB_RET_SUCCESS) {
         return ret;
     }
 
-    ret = 0;
+    ret = USB_RET_SUCCESS;
     switch (request) {
     case WACOM_SET_REPORT:
         if (s->mouse_grabbed) {
@@ -269,27 +269,25 @@ 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;
@@ -302,7 +300,7 @@ static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
 {
     USBWacomState *s = (USBWacomState *) dev;
     uint8_t buf[p->iov.size];
-    int ret = 0;
+    int len = 0, ret = USB_RET_SUCCESS;
 
     switch (p->pid) {
     case USB_TOKEN_IN:
@@ -311,10 +309,10 @@ static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
                 return USB_RET_NAK;
             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.  */
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 18cf097..3e74372 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1458,7 +1458,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;
@@ -1466,7 +1466,7 @@ 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;
+    p->usb_status = packet->status ? packet->status : packet->actual_length;
 
     if (p->queue->async) {
         qemu_bh_schedule(p->queue->ehci->async_bh);
@@ -1599,6 +1599,9 @@ 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);
+    if (ret == USB_RET_SUCCESS) {
+        ret = p->packet.actual_length;
+    }
     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);
@@ -1667,6 +1670,9 @@ static int ehci_process_itd(EHCIState *ehci,
                 usb_packet_map(&ehci->ipacket, &ehci->isgl);
                 ret = usb_handle_packet(dev, &ehci->ipacket);
                 assert(ret != USB_RET_ASYNC);
+                if (ret == USB_RET_SUCCESS) {
+                    ret = ehci->ipacket.actual_length;
+                }
                 usb_packet_unmap(&ehci->ipacket, &ehci->isgl);
             } else {
                 DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c
index a6105d3..02cfa18 100644
--- a/hw/usb/hcd-musb.c
+++ b/hw/usb/hcd-musb.c
@@ -633,6 +633,9 @@ static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
     ep->packey[dir].dir = dir;
 
     ret = usb_handle_packet(dev, &ep->packey[dir].p);
+    if (ret == USB_RET_SUCCESS) {
+        ret = ep->packey[dir].p.actual_length;
+    }
 
     if (ret == USB_RET_ASYNC) {
         usb_device_flush_ep_queue(dev, uep);
@@ -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 4c77600..94a5c01 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -808,7 +808,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
     }
 
     if (completion) {
-        ret = ohci->usb_packet.result;
+        ret = ohci->usb_packet.status;
     } else {
         bool int_req = relative_frame_number == frame_count &&
                        OHCI_BM(iso_td.flags, TD_DI) == 0;
@@ -822,6 +822,9 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
             return 1;
         }
     }
+    if (ret == USB_RET_SUCCESS) {
+        ret = ohci->usb_packet.actual_length;
+    }
 
 #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,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
     }
 #endif
     if (completion) {
-        ret = ohci->usb_packet.result;
+        ret = ohci->usb_packet.status;
         ohci->async_td = 0;
         ohci->async_complete = 0;
     } else {
@@ -1027,6 +1030,9 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
             return 1;
         }
     }
+    if (ret == USB_RET_SUCCESS) {
+        ret = ohci->usb_packet.actual_length;
+    }
     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 4a1ea6b..65b63d3 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -705,21 +705,20 @@ static void uhci_process_frame(UHCIState *s);
 */
 static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
 {
-    int len = 0, max_len, err, ret;
+    int len = 0, max_len, err;
     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)
+    if (async->packet.status != USB_RET_SUCCESS) {
         goto out;
+    }
 
-    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
@@ -744,7 +743,7 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
     return TD_RESULT_COMPLETE;
 
 out:
-    switch(ret) {
+    switch (async->packet.status) {
     case USB_RET_STALL:
         td->ctrl |= TD_CTRL_STALL;
         td->ctrl &= ~TD_CTRL_ACTIVE;
@@ -806,7 +805,7 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
                           struct USBEndpoint **ep_ret)
 {
     UHCIAsync *async;
-    int len = 0, max_len;
+    int ret, max_len;
     uint8_t pid;
     bool spd;
     USBDevice *dev;
@@ -868,13 +867,14 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
     switch(pid) {
     case USB_TOKEN_OUT:
     case USB_TOKEN_SETUP:
-        len = usb_handle_packet(dev, &async->packet);
-        if (len >= 0)
-            len = max_len;
+        ret = usb_handle_packet(dev, &async->packet);
+        if (ret == USB_RET_SUCCESS) {
+            async->packet.actual_length = max_len;
+        }
         break;
 
     case USB_TOKEN_IN:
-        len = usb_handle_packet(dev, &async->packet);
+        ret = usb_handle_packet(dev, &async->packet);
         break;
 
     default:
@@ -885,19 +885,19 @@ static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td,
         uhci_update_irq(s);
         return TD_RESULT_STOP_FRAME;
     }
- 
-    if (len == USB_RET_ASYNC) {
+
+    if (ret == USB_RET_ASYNC) {
         uhci_async_link(async);
         return TD_RESULT_ASYNC_START;
     }
 
-    async->packet.result = len;
+    async->packet.status = ret;
 
 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)
@@ -905,7 +905,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 21c3386..ffba6de 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1356,7 +1356,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.status ? 0 : xfer->packet.actual_length;
 
     for (i = 0; i < xfer->trb_count; i++) {
         XHCITRB *trb = &xfer->trbs[i];
@@ -1491,8 +1491,8 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
         xhci_xfer_unmap(xfer);
     }
 
-    if (ret >= 0) {
-        trace_usb_xhci_xfer_success(xfer, ret);
+    if (ret == USB_RET_SUCCESS) {
+        trace_usb_xhci_xfer_success(xfer, xfer->packet.actual_length);
         xfer->status = CC_SUCCESS;
         xhci_xfer_report(xfer);
         return 0;
@@ -2840,11 +2840,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, packet->status);
     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..3968f30 100644
--- a/hw/usb/host-bsd.c
+++ b/hw/usb/host-bsd.c
@@ -139,7 +139,7 @@ static int usb_host_handle_control(USBDevice *dev,
 
         /* specific SET_ADDRESS support */
         dev->addr = value;
-        return 0;
+        return USB_RET_SUCCESS;
     } else if ((request >> 8) == UT_WRITE_DEVICE &&
                (request & 0xff) == UR_SET_CONFIG) {
 
@@ -154,7 +154,7 @@ static int usb_host_handle_control(USBDevice *dev,
             return USB_RET_STALL;
         }
 
-        return 0;
+        return USB_RET_SUCCESS;
     } else if ((request >> 8) == UT_WRITE_INTERFACE &&
                (request & 0xff) == UR_SET_INTERFACE) {
 
@@ -171,7 +171,7 @@ static int usb_host_handle_control(USBDevice *dev,
             return USB_RET_STALL;
         }
 
-        return 0;
+        return USB_RET_SUCCESS;
     } else {
         req.ucr_request.bmRequestType = request >> 8;
         req.ucr_request.bRequest = request & 0xff;
@@ -203,7 +203,8 @@ static int usb_host_handle_control(USBDevice *dev,
 #endif
             return USB_RET_NAK; // STALL
         } else {
-            return req.ucr_actlen;
+            p->actual_length = req.ucr_actlen;
+            return USB_RET_SUCCESS;
         }
     }
 }
@@ -272,7 +273,8 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
             return USB_RET_STALL;
         }
     } else {
-        return ret;
+        p->actual_length = ret;
+        return USB_RET_SUCCESS;
     }
 }
 
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index 3a258b4..9857292 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;
                 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);
             }
         }
@@ -748,7 +749,7 @@ static int urb_status_to_usb_ret(int status)
 static int 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, ret = USB_RET_SUCCESS;
     uint8_t *buf;
 
     max_packet_size = p->ep->max_packet_size;
@@ -766,18 +767,18 @@ 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);
+                ret = urb_status_to_usb_ret(aurb[i].urb.status);
                 /* 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(
+                ret = urb_status_to_usb_ret(
                                         aurb[i].urb.iso_frame_desc[j].status);
             /* 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;
+                ret = USB_RET_BABBLE;
             /* All good copy data over */
             } else {
                 len = aurb[i].urb.iso_frame_desc[j].actual_length;
@@ -823,17 +824,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 || ret == USB_RET_SUCCESS) {
                         switch(errno) {
                         case ETIMEDOUT:
-                            len = USB_RET_NAK;
+                            ret = USB_RET_NAK;
                             break;
                         case EPIPE:
                         default:
-                            len = USB_RET_STALL;
+                            ret = USB_RET_STALL;
                         }
                     }
                     break;
@@ -844,7 +844,7 @@ static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
         }
     }
 
-    return len;
+    return ret;
 }
 
 static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
@@ -959,7 +959,7 @@ static int 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;
+    return USB_RET_SUCCESS;
 }
 
 static int usb_host_set_config(USBHostDevice *s, int config)
@@ -991,7 +991,7 @@ again:
     }
     usb_host_claim_interfaces(s, config);
     usb_linux_update_endp_table(s);
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
@@ -1027,7 +1027,7 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
 
     s->dev.altsetting[iface] = alt;
     usb_linux_update_endp_table(s);
-    return 0;
+    return USB_RET_SUCCESS;
 }
 
 static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
@@ -1068,12 +1068,12 @@ 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 USB_RET_SUCCESS;
         }
     }
 
     /* The rest are asynchronous */
-    assert(p && p->result == 0);
+    assert(p && p->status == USB_RET_SUCCESS);
 
     if (length > sizeof(dev->data_buf)) {
         fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 2c5377c..040582c 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 int usbredir_handle_status(USBRedirDevice *dev, USBPacket *p,
+    int status);
 
 #define VERSION "qemu usb-redir guest " QEMU_VERSION
 
@@ -506,7 +506,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 USB_RET_SUCCESS;
             }
             dev->endpoint[EP2I(ep)].bufpq_prefilled = 1;
         }
@@ -540,7 +540,7 @@ static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
         }
         usb_packet_copy(p, isop->data, len);
         bufp_free(dev, isop, ep);
-        return len;
+        return USB_RET_SUCCESS;
     } else {
         /* If the stream was not started because of a pending error don't
            send the packet to the usb-host */
@@ -560,7 +560,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);
+        return usbredir_handle_status(dev, p, status);
     }
 }
 
@@ -649,7 +649,7 @@ 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);
+                return usbredir_handle_status(dev, p, status);
             }
             return USB_RET_NAK;
         }
@@ -659,7 +659,7 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
         status = intp->status;
         if (status != usb_redir_success) {
             bufp_free(dev, intp, ep);
-            return usbredir_handle_status(dev, status, 0);
+            return usbredir_handle_status(dev, p, status);
         }
 
         len = intp->len;
@@ -670,7 +670,7 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
         }
         usb_packet_copy(p, intp->data, len);
         bufp_free(dev, intp, ep);
-        return len;
+        return USB_RET_SUCCESS;
     } else {
         /* Output interrupt endpoint, normal async operation */
         struct usb_redir_interrupt_packet_header interrupt_packet;
@@ -1184,30 +1184,39 @@ error:
  * usbredirparser packet complete callbacks
  */
 
-static int usbredir_handle_status(USBRedirDevice *dev,
-                                       int status, int actual_len)
+static int usbredir_handle_status(USBRedirDevice *dev, USBPacket *p,
+    int status)
 {
+    int ret;
+
     switch (status) {
     case usb_redir_success:
-        return actual_len;
+        ret = USB_RET_SUCCESS;
+        break;
     case usb_redir_stall:
-        return USB_RET_STALL;
+        ret = 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;
+        ret = USB_RET_IOERROR;
+        break;
     case usb_redir_inval:
         WARNING("got invalid param error from usb-host?\n");
-        return USB_RET_IOERROR;
+        ret = USB_RET_IOERROR;
+        break;
     case usb_redir_babble:
-        return USB_RET_BABBLE;
+        ret = USB_RET_BABBLE;
+        break;
     case usb_redir_ioerror:
     case usb_redir_timeout:
     default:
-        return USB_RET_IOERROR;
+        ret = USB_RET_IOERROR;
     }
+    p->status = ret;
+    return ret;
 }
 
 static void usbredir_hello(void *priv, struct usb_redir_hello_header *h)
@@ -1437,7 +1446,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);
@@ -1446,9 +1454,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);
     }
 }
@@ -1458,7 +1466,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,
@@ -1468,10 +1475,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);
     }
 }
@@ -1547,18 +1553,19 @@ 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 (p->status == USB_RET_SUCCESS) {
             usbredir_log_data(dev, "ctrl data in:", data, data_len);
             if (data_len <= sizeof(dev->dev.data_buf)) {
                 memcpy(dev->dev.data_buf, data, data_len);
             } else {
                 ERROR("ctrl buffer too small (%d > %zu)\n",
                       data_len, sizeof(dev->dev.data_buf));
-                len = USB_RET_STALL;
+                p->status = USB_RET_STALL;
+                len = 0;
             }
         }
-        p->result = len;
+        p->actual_length = len;
         usb_generic_async_ctrl_complete(&dev->dev, p);
     }
     free(data);
@@ -1579,8 +1586,8 @@ 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 (p->status == USB_RET_SUCCESS) {
             usbredir_log_data(dev, "bulk data in:", data, data_len);
             if (data_len <= size) {
                 if (p->combined) {
@@ -1592,10 +1599,11 @@ static void usbredir_bulk_packet(void *priv, uint64_t id,
             } else {
                 ERROR("bulk got more data then requested (%d > %zd)\n",
                       data_len, p->iov.size);
-                len = USB_RET_BABBLE;
+                p->status = USB_RET_BABBLE;
+                len = 0;
             }
         }
-        p->result = len;
+        p->actual_length = len;
         if (p->pid == USB_TOKEN_IN && p->ep->pipeline) {
             usb_combined_input_packet_complete(&dev->dev, p);
         } else {
@@ -1661,8 +1669,8 @@ static void usbredir_interrupt_packet(void *priv, uint64_t id,
 
         USBPacket *p = usbredir_find_packet_by_id(dev, ep, id);
         if (p) {
-            p->result = usbredir_handle_status(dev,
-                                               interrupt_packet->status, len);
+            usbredir_handle_status(dev, p, interrupt_packet->status);
+            p->actual_length = len;
             usb_packet_complete(&dev->dev, p);
         }
     }
