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