]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/usb/dev-hub.c
Merge remote-tracking branch 'aneesh/for-upstream' into staging
[mirror_qemu.git] / hw / usb / dev-hub.c
index eb4e71120741e84eeced764ac1c29814e90e359c..470fbbb86cfbadea62c5dee609bddb5753392268 100644 (file)
  * THE SOFTWARE.
  */
 #include "qemu-common.h"
+#include "trace.h"
 #include "hw/usb.h"
 #include "hw/usb/desc.h"
 
-//#define DEBUG
-
 #define NUM_PORTS 8
 
 typedef struct USBHubPort {
@@ -91,7 +90,7 @@ enum {
 };
 
 static const USBDescStrings desc_strings = {
-    [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+    [STR_MANUFACTURER] = "QEMU",
     [STR_PRODUCT]      = "QEMU USB Hub",
     [STR_SERIALNUMBER] = "314159",
 };
@@ -157,6 +156,7 @@ static void usb_hub_attach(USBPort *port1)
     USBHubState *s = port1->opaque;
     USBHubPort *port = &s->ports[port1->index];
 
+    trace_usb_hub_attach(s->dev.addr, port1->index + 1);
     port->wPortStatus |= PORT_STAT_CONNECTION;
     port->wPortChange |= PORT_STAT_C_CONNECTION;
     if (port->port.dev->speed == USB_SPEED_LOW) {
@@ -172,6 +172,7 @@ static void usb_hub_detach(USBPort *port1)
     USBHubState *s = port1->opaque;
     USBHubPort *port = &s->ports[port1->index];
 
+    trace_usb_hub_detach(s->dev.addr, port1->index + 1);
     usb_wakeup(s->intr);
 
     /* Let upstream know the device on this port is gone */
@@ -183,6 +184,7 @@ static void usb_hub_detach(USBPort *port1)
         port->wPortStatus &= ~PORT_STAT_ENABLE;
         port->wPortChange |= PORT_STAT_C_ENABLE;
     }
+    usb_wakeup(s->intr);
 }
 
 static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
@@ -247,6 +249,7 @@ static void usb_hub_handle_reset(USBDevice *dev)
     USBHubPort *port;
     int i;
 
+    trace_usb_hub_reset(s->dev.addr);
     for (i = 0; i < NUM_PORTS; i++) {
         port = s->ports + i;
         port->wPortStatus = PORT_STAT_POWER;
@@ -261,15 +264,42 @@ static void usb_hub_handle_reset(USBDevice *dev)
     }
 }
 
-static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
+static const char *feature_name(int feature)
+{
+    static const char *name[] = {
+        [PORT_CONNECTION]    = "connection",
+        [PORT_ENABLE]        = "enable",
+        [PORT_SUSPEND]       = "suspend",
+        [PORT_OVERCURRENT]   = "overcurrent",
+        [PORT_RESET]         = "reset",
+        [PORT_POWER]         = "power",
+        [PORT_LOWSPEED]      = "lowspeed",
+        [PORT_HIGHSPEED]     = "highspeed",
+        [PORT_C_CONNECTION]  = "change connection",
+        [PORT_C_ENABLE]      = "change enable",
+        [PORT_C_SUSPEND]     = "change suspend",
+        [PORT_C_OVERCURRENT] = "change overcurrent",
+        [PORT_C_RESET]       = "change reset",
+        [PORT_TEST]          = "test",
+        [PORT_INDICATOR]     = "indicator",
+    };
+    if (feature < 0 || feature >= ARRAY_SIZE(name)) {
+        return "?";
+    }
+    return name[feature] ?: "?";
+}
+
+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;
     int ret;
 
+    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) {
-        return ret;
+        return;
     }
 
     switch(request) {
@@ -277,7 +307,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:
@@ -285,7 +314,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:
         {
@@ -295,26 +324,31 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
                 goto fail;
             }
             port = &s->ports[n];
+            trace_usb_hub_get_port_status(s->dev.addr, index,
+                                          port->wPortStatus,
+                                          port->wPortChange);
             data[0] = port->wPortStatus;
             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:
         {
             unsigned int n = index - 1;
             USBHubPort *port;
             USBDevice *dev;
+
+            trace_usb_hub_set_port_feature(s->dev.addr, index,
+                                           feature_name(value));
+
             if (n >= NUM_PORTS) {
                 goto fail;
             }
@@ -330,6 +364,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
                     port->wPortChange |= PORT_STAT_C_RESET;
                     /* set enable bit */
                     port->wPortStatus |= PORT_STAT_ENABLE;
+                    usb_wakeup(s->intr);
                 }
                 break;
             case PORT_POWER:
@@ -337,7 +372,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
             default:
                 goto fail;
             }
-            ret = 0;
         }
         break;
     case ClearPortFeature:
@@ -345,6 +379,9 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
             unsigned int n = index - 1;
             USBHubPort *port;
 
+            trace_usb_hub_clear_port_feature(s->dev.addr, index,
+                                             feature_name(value));
+
             if (n >= NUM_PORTS) {
                 goto fail;
             }
@@ -374,7 +411,6 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
             default:
                 goto fail;
             }
-            ret = 0;
         }
         break;
     case GetHubDescriptor:
@@ -398,22 +434,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:
@@ -426,7 +460,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++) {
@@ -439,9 +474,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;
@@ -450,10 +484,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)
@@ -481,6 +514,7 @@ static int usb_hub_initfn(USBDevice *dev)
     USBHubPort *port;
     int i;
 
+    usb_desc_create_serial(dev);
     usb_desc_init(dev);
     s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
     for (i = 0; i < NUM_PORTS; i++) {