summary refs log tree commit diff stats
path: root/hw/usb/core.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-01-23 14:40:45 +0000
committerPeter Maydell <peter.maydell@linaro.org>2021-01-23 14:40:45 +0000
commite93c65a6c64fa18b0c61fb9338d364cbea32b6ef (patch)
tree5f1c30bca7461c74fdb80ae941adae550aea8d1b /hw/usb/core.c
parent0e32462630687a18039464511bd0447ada5709c3 (diff)
parent2980a316734c420e7398aec026909dcfc8614c1d (diff)
downloadfocaccia-qemu-e93c65a6c64fa18b0c61fb9338d364cbea32b6ef.tar.gz
focaccia-qemu-e93c65a6c64fa18b0c61fb9338d364cbea32b6ef.zip
Merge remote-tracking branch 'remotes/kraxel/tags/usb-20210122-pull-request' into staging
usb: cleanups and fixes.
usb: add pcap support.

# gpg: Signature made Fri 22 Jan 2021 17:48:35 GMT
# gpg:                using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/usb-20210122-pull-request:
  usb-host: map LIBUSB_SPEED_SUPER_PLUS to USB_SPEED_SUPER
  usb: add pcap support.
  hw/usb/dev-uas: Report command additional adb length as unsupported
  scsi/utils: Add INVALID_PARAM_VALUE sense code definition
  hw/usb/hcd-xhci: Fix extraneous format-truncation error on 32-bit hosts
  hw/usb: Convert to qdev_realize()
  hw/usb: Fix bad printf format specifiers
  hw/usb/host-libusb.c: fix build with kernel < 5.0

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/usb/core.c')
-rw-r--r--hw/usb/core.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/hw/usb/core.c b/hw/usb/core.c
index e960036f4d..975f76250a 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -142,7 +142,7 @@ static void do_token_setup(USBDevice *s, USBPacket *p)
     setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
     if (setup_len > sizeof(s->data_buf)) {
         fprintf(stderr,
-                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
+                "usb_generic_handle_packet: ctrl buffer too small (%u > %zu)\n",
                 setup_len, sizeof(s->data_buf));
         p->status = USB_RET_STALL;
         return;
@@ -154,6 +154,7 @@ static void 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) {
+        usb_pcap_ctrl(p, true);
         usb_device_handle_control(s, p, request, value, index,
                                   s->setup_len, s->data_buf);
         if (p->status == USB_RET_ASYNC) {
@@ -190,6 +191,7 @@ static void do_token_in(USBDevice *s, USBPacket *p)
     switch(s->setup_state) {
     case SETUP_STATE_ACK:
         if (!(s->setup_buf[0] & USB_DIR_IN)) {
+            usb_pcap_ctrl(p, true);
             usb_device_handle_control(s, p, request, value, index,
                                       s->setup_len, s->data_buf);
             if (p->status == USB_RET_ASYNC) {
@@ -197,6 +199,7 @@ static void do_token_in(USBDevice *s, USBPacket *p)
             }
             s->setup_state = SETUP_STATE_IDLE;
             p->actual_length = 0;
+            usb_pcap_ctrl(p, false);
         }
         break;
 
@@ -215,6 +218,7 @@ static void do_token_in(USBDevice *s, USBPacket *p)
         }
         s->setup_state = SETUP_STATE_IDLE;
         p->status = USB_RET_STALL;
+        usb_pcap_ctrl(p, false);
         break;
 
     default:
@@ -230,6 +234,7 @@ static void do_token_out(USBDevice *s, USBPacket *p)
     case SETUP_STATE_ACK:
         if (s->setup_buf[0] & USB_DIR_IN) {
             s->setup_state = SETUP_STATE_IDLE;
+            usb_pcap_ctrl(p, false);
             /* transfer OK */
         } else {
             /* ignore additional output */
@@ -251,6 +256,7 @@ static void do_token_out(USBDevice *s, USBPacket *p)
         }
         s->setup_state = SETUP_STATE_IDLE;
         p->status = USB_RET_STALL;
+        usb_pcap_ctrl(p, false);
         break;
 
     default:
@@ -277,7 +283,7 @@ static void do_parameter(USBDevice *s, USBPacket *p)
     setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
     if (setup_len > sizeof(s->data_buf)) {
         fprintf(stderr,
-                "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n",
+                "usb_generic_handle_packet: ctrl buffer too small (%u > %zu)\n",
                 setup_len, sizeof(s->data_buf));
         p->status = USB_RET_STALL;
         return;
@@ -288,6 +294,7 @@ static void do_parameter(USBDevice *s, USBPacket *p)
         usb_packet_copy(p, s->data_buf, s->setup_len);
     }
 
+    usb_pcap_ctrl(p, true);
     usb_device_handle_control(s, p, request, value, index,
                               s->setup_len, s->data_buf);
     if (p->status == USB_RET_ASYNC) {
@@ -301,6 +308,7 @@ static void do_parameter(USBDevice *s, USBPacket *p)
         p->actual_length = 0;
         usb_packet_copy(p, s->data_buf, s->setup_len);
     }
+    usb_pcap_ctrl(p, false);
 }
 
 /* ctrl complete function for devices which use usb_generic_handle_packet and
@@ -311,6 +319,7 @@ void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
 {
     if (p->status < 0) {
         s->setup_state = SETUP_STATE_IDLE;
+        usb_pcap_ctrl(p, false);
     }
 
     switch (s->setup_state) {
@@ -325,6 +334,7 @@ void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p)
     case SETUP_STATE_ACK:
         s->setup_state = SETUP_STATE_IDLE;
         p->actual_length = 0;
+        usb_pcap_ctrl(p, false);
         break;
 
     case SETUP_STATE_PARAM:
@@ -359,12 +369,14 @@ USBDevice *usb_find_device(USBPort *port, uint8_t addr)
 static void usb_process_one(USBPacket *p)
 {
     USBDevice *dev = p->ep->dev;
+    bool nak;
 
     /*
      * 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().
      */
+    nak = (p->status == USB_RET_NAK);
     p->status = USB_RET_SUCCESS;
 
     if (p->ep->nr == 0) {
@@ -388,6 +400,9 @@ static void usb_process_one(USBPacket *p)
         }
     } else {
         /* data pipe */
+        if (!nak) {
+            usb_pcap_data(p, true);
+        }
         usb_device_handle_data(dev, p);
     }
 }
@@ -439,6 +454,7 @@ void usb_handle_packet(USBDevice *dev, USBPacket *p)
             assert(p->stream || !p->ep->pipeline ||
                    QTAILQ_EMPTY(&p->ep->queue));
             if (p->status != USB_RET_NAK) {
+                usb_pcap_data(p, false);
                 usb_packet_set_state(p, USB_PACKET_COMPLETE);
             }
         }
@@ -458,6 +474,7 @@ void usb_packet_complete_one(USBDevice *dev, USBPacket *p)
             (p->short_not_ok && (p->actual_length < p->iov.size))) {
         ep->halted = true;
     }
+    usb_pcap_data(p, false);
     usb_packet_set_state(p, USB_PACKET_COMPLETE);
     QTAILQ_REMOVE(&ep->queue, p, queue);
     dev->port->ops->complete(dev->port, p);