r1924 - in trunk/src/host/qemu-neo1973: . hw

andrew at sita.openmoko.org andrew at sita.openmoko.org
Tue May 8 01:11:18 CEST 2007


Author: andrew
Date: 2007-05-08 01:11:17 +0200 (Tue, 08 May 2007)
New Revision: 1924

Modified:
   trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c
   trunk/src/host/qemu-neo1973/usb-linux-gadget.c
Log:
Add high-speed USB slaves support and account for all the quirks related to this.
Misc bugfixes and added verbosity.


Modified: trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c	2007-05-07 22:54:10 UTC (rev 1923)
+++ trunk/src/host/qemu-neo1973/hw/s3c24xx_udc.c	2007-05-07 23:11:17 UTC (rev 1924)
@@ -545,7 +545,7 @@
         s3c_udc_interrupt(s, -1);
         break;
     case USB_TOKEN_SETUP:
-        if (unlikely(s->ep0.packet))
+        if (unlikely(s->ep0.packet || (s->ep0.csr & (1 << 0))))	/* OUT_PKT_R */
             printf("%s: EP0 overrun\n", __FUNCTION__);
         if (s->ep0.csr & (1 << 5)) {			/* SEND_STALL */
             ret = USB_RET_STALL;
@@ -651,8 +651,21 @@
     return ret;
 }
 
-static void s3c_udc_handle_destroy(USBDevice *s)
+static void s3c_udc_handle_destroy(USBDevice *dev)
 {
+    struct s3c_udc_state_s *s = (struct s3c_udc_state_s *) dev->opaque;
+    int i;
+    s->ep0.len = 0;
+    s->ep0.csr = 0x00;
+    s->ep0.packet = 0;
+    for (i = 0; i < S3C_EPS - 1; i ++) {
+        s->ep1[i].len = 0;
+        s->ep1[i].in_csr[0] = 0;
+        s->ep1[i].in_csr[1] = 0;
+        s->ep1[i].out_csr[0] = 0;
+        s->ep1[i].out_csr[1] = 0;
+        s->ep1[i].packet = 0;
+    }
 }
 
 struct s3c_udc_state_s *s3c_udc_init(target_phys_addr_t base,

Modified: trunk/src/host/qemu-neo1973/usb-linux-gadget.c
===================================================================
--- trunk/src/host/qemu-neo1973/usb-linux-gadget.c	2007-05-07 22:54:10 UTC (rev 1923)
+++ trunk/src/host/qemu-neo1973/usb-linux-gadget.c	2007-05-07 23:11:17 UTC (rev 1924)
@@ -283,7 +283,12 @@
     dst += desc->bLength;
     dl += desc->bLength;
 
-    /* XXX write highspeed descriptor if hci->hosthighspeed */
+    if (hci->hosthighspeed) {
+        /* Send the same information again as high-speed descriptors */
+        memcpy(dst, desc, desc->bLength);
+        dst += desc->bLength;
+        dl += desc->bLength;
+    }
 
     ret = write(ep->fd, buffer, dl);
     if (ret < dl) {
@@ -345,8 +350,8 @@
             if (ret < 0) {
                 if (ret != -ESHUTDOWN)
                     goto fail;
-                fprintf(stderr, "%s: EPs not configured due to disconnect\n",
-                                __FUNCTION__);
+                fprintf(stderr, "%s: EPs not configured due to disconnect - "
+                                "will retry\n", __FUNCTION__);
                 return;
             }
         }
@@ -364,7 +369,21 @@
 static void gadget_desc_parse(USBPacket *packet, void *opaque)
 {
     struct gadget_state_s *hci = (struct gadget_state_s *) opaque;
+    uint8_t *p;
     hci->desc_len = packet->len;
+
+    /* HACK: report always only a single Configuration */
+    ((struct usb_device_descriptor *) hci->dev_desc)->bNumConfigurations = 1;
+
+    if (hci->hosthighspeed) {
+        /* We need to fake a USB 2.0 device if we're already faking
+         * a high-speed device (due to gadgetfs limitations).  */
+        p = (uint8_t *) &((struct usb_device_descriptor *)
+                        hci->dev_desc)->bcdUSB;
+        p[0] = 0x20;
+        p[1] = 0x00;
+    }
+
     gadget_run(packet, hci);
 }
 
@@ -373,6 +392,7 @@
     struct gadget_state_s *hci = (struct gadget_state_s *) opaque;
     uint8_t buffer[4096];
     int dl = 0;
+    int sl = 0;
     struct usb_config_descriptor *cfg;
     struct usb_descriptor_header *src =
             (struct usb_descriptor_header *) packet->data;
@@ -396,19 +416,41 @@
         goto fail;
     cfg->bMaxPower = 0x00;
     cfg->bmAttributes = 0xc0; /* dummy_hcd is picky about power */
+
+    if (hci->hosthighspeed) {
+        /* For high-speed devies we need to set the interval for
+         * Interrupt Enpoints as high as possible so that the host doesn't
+         * expect really fast responses from the emulator and thus
+         * time-out on some packets.  */
+        while (sl < cfg->wTotalLength) {
+            if (src->bDescriptorType == USB_DT_ENDPOINT) {
+                if (((struct usb_endpoint_descriptor *) src)->bmAttributes ==
+                                USB_ENDPOINT_XFER_INT)
+                    ((struct usb_endpoint_descriptor *) src)->bInterval = 0x0e;
+            }
+            sl += src->bLength;
+            src = (typeof(src)) ((uint8_t *) src + src->bLength);
+        }
+    }
+
     memcpy(dst, cfg, cfg->wTotalLength);
     memcpy(&hci->config_desc, cfg, cfg->wTotalLength);
     dl += cfg->wTotalLength;
     dst += cfg->wTotalLength;
 
-    /* XXX write highspeed descriptor if hci->hosthighspeed */
+    if (hci->hosthighspeed) {
+        /* Send the same information again as high-speed descriptors */
+        if (dl + cfg->wTotalLength > sizeof(buffer))
+            goto fail;
+        memcpy(dst, cfg, cfg->wTotalLength);
+        dl += cfg->wTotalLength;
+        dst += cfg->wTotalLength;
+    }
 
     /* Write the device descriptor */
     if (dl + hci->desc_len > sizeof(buffer))
         goto fail;
     memcpy(dst, hci->dev_desc, hci->desc_len);
-    /* HACK: report always only a single Configuration */
-    ((struct usb_device_descriptor *) dst)->bNumConfigurations = 1;
     dl += hci->desc_len;
     dst += hci->desc_len;
 
@@ -721,6 +763,8 @@
     return -ENOENT;
 
 found:
+    /* XXX gadgetfs seems to always believe it's high-speed */
+    s->hosthighspeed = 1;
     return 0;
 }
 





More information about the commitlog mailing list