summary refs log tree commit diff stats
path: root/hw/usb-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb-hub.c')
-rw-r--r--hw/usb-hub.c98
1 files changed, 22 insertions, 76 deletions
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 6e2a35839d..c49c547d0c 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -138,74 +138,6 @@ static const USBDesc desc_hub = {
     .str  = desc_strings,
 };
 
-static const uint8_t qemu_hub_dev_descriptor[] = {
-	0x12,       /*  u8 bLength; */
-	0x01,       /*  u8 bDescriptorType; Device */
-	0x10, 0x01, /*  u16 bcdUSB; v1.1 */
-
-	0x09,	    /*  u8  bDeviceClass; HUB_CLASSCODE */
-	0x00,	    /*  u8  bDeviceSubClass; */
-	0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
-	0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
-
-	0x00, 0x00, /*  u16 idVendor; */
- 	0x00, 0x00, /*  u16 idProduct; */
-	0x01, 0x01, /*  u16 bcdDevice */
-
-	0x03,       /*  u8  iManufacturer; */
-	0x02,       /*  u8  iProduct; */
-	0x01,       /*  u8  iSerialNumber; */
-	0x01        /*  u8  bNumConfigurations; */
-};
-
-/* XXX: patch interrupt size */
-static const uint8_t qemu_hub_config_descriptor[] = {
-
-	/* one configuration */
-	0x09,       /*  u8  bLength; */
-	0x02,       /*  u8  bDescriptorType; Configuration */
-	0x19, 0x00, /*  u16 wTotalLength; */
-	0x01,       /*  u8  bNumInterfaces; (1) */
-	0x01,       /*  u8  bConfigurationValue; */
-	0x00,       /*  u8  iConfiguration; */
-	0xe0,       /*  u8  bmAttributes;
-				 Bit 7: must be set,
-				     6: Self-powered,
-				     5: Remote wakeup,
-				     4..0: resvd */
-	0x00,       /*  u8  MaxPower; */
-
-	/* USB 1.1:
-	 * USB 2.0, single TT organization (mandatory):
-	 *	one interface, protocol 0
-	 *
-	 * USB 2.0, multiple TT organization (optional):
-	 *	two interfaces, protocols 1 (like single TT)
-	 *	and 2 (multiple TT mode) ... config is
-	 *	sometimes settable
-	 *	NOT IMPLEMENTED
-	 */
-
-	/* one interface */
-	0x09,       /*  u8  if_bLength; */
-	0x04,       /*  u8  if_bDescriptorType; Interface */
-	0x00,       /*  u8  if_bInterfaceNumber; */
-	0x00,       /*  u8  if_bAlternateSetting; */
-	0x01,       /*  u8  if_bNumEndpoints; */
-	0x09,       /*  u8  if_bInterfaceClass; HUB_CLASSCODE */
-	0x00,       /*  u8  if_bInterfaceSubClass; */
-	0x00,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
-	0x00,       /*  u8  if_iInterface; */
-
-	/* one endpoint (status change endpoint) */
-	0x07,       /*  u8  ep_bLength; */
-	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
-	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
- 	0x02, 0x00, /*  u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
-	0xff        /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
-};
-
 static const uint8_t qemu_hub_hub_descriptor[] =
 {
 	0x00,			/*  u8  bLength; patched in later */
@@ -238,6 +170,9 @@ static void usb_hub_detach(USBPort *port1)
     USBHubState *s = port1->opaque;
     USBHubPort *port = &s->ports[port1->index];
 
+    /* Let upstream know the device on this port is gone */
+    s->dev.port->ops->child_detach(s->dev.port, port1->dev);
+
     port->wPortStatus &= ~PORT_STAT_CONNECTION;
     port->wPortChange |= PORT_STAT_C_CONNECTION;
     if (port->wPortStatus & PORT_STAT_ENABLE) {
@@ -246,10 +181,18 @@ static void usb_hub_detach(USBPort *port1)
     }
 }
 
-static void usb_hub_wakeup(USBDevice *dev)
+static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
+{
+    USBHubState *s = port1->opaque;
+
+    /* Pass along upstream */
+    s->dev.port->ops->child_detach(s->dev.port, child);
+}
+
+static void usb_hub_wakeup(USBPort *port1)
 {
-    USBHubState *s = dev->port->opaque;
-    USBHubPort *port = &s->ports[dev->port->index];
+    USBHubState *s = port1->opaque;
+    USBHubPort *port = &s->ports[port1->index];
 
     if (port->wPortStatus & PORT_STAT_SUSPEND) {
         port->wPortChange |= PORT_STAT_C_SUSPEND;
@@ -257,9 +200,9 @@ static void usb_hub_wakeup(USBDevice *dev)
     }
 }
 
-static void usb_hub_complete(USBDevice *dev, USBPacket *packet)
+static void usb_hub_complete(USBPort *port, USBPacket *packet)
 {
-    USBHubState *s = dev->port->opaque;
+    USBHubState *s = port->opaque;
 
     /*
      * Just pass it along upstream for now.
@@ -451,11 +394,12 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
         if (p->devep == 1) {
             USBHubPort *port;
             unsigned int status;
+            uint8_t buf[4];
             int i, n;
             n = (NUM_PORTS + 1 + 7) / 8;
-            if (p->len == 1) { /* FreeBSD workaround */
+            if (p->iov.size == 1) { /* FreeBSD workaround */
                 n = 1;
-            } else if (n > p->len) {
+            } else if (n > p->iov.size) {
                 return USB_RET_BABBLE;
             }
             status = 0;
@@ -466,8 +410,9 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
             }
             if (status != 0) {
                 for(i = 0; i < n; i++) {
-                    p->data[i] = status >> (8 * i);
+                    buf[i] = status >> (8 * i);
                 }
+                usb_packet_copy(p, buf, n);
                 ret = n;
             } else {
                 ret = USB_RET_NAK; /* usb11 11.13.1 */
@@ -537,6 +482,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
 static USBPortOps usb_hub_port_ops = {
     .attach = usb_hub_attach,
     .detach = usb_hub_detach,
+    .child_detach = usb_hub_child_detach,
     .wakeup = usb_hub_wakeup,
     .complete = usb_hub_complete,
 };