ChangeSet 1.1455.1.25, 2003/07/15 14:53:55-07:00, david-b@pacbell.net [PATCH] USB: usbtest, autoconfigure from descriptors Not all gadget controllers support ep2in-bulk and ep2out-bulk, unlike the EZ-USB (non-FX2) devices or the net2280. So this patch teaches "usbtest" how to look at the descriptors it's given, and use the appropriate endpoints. This helps support Linux test devices using hardware like the pxa2xx UDC, and other controllers. drivers/usb/misc/usbtest.c | 103 ++++++++++++++++++++++++++++++++++++++------- 1 files changed, 88 insertions(+), 15 deletions(-) diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c --- a/drivers/usb/misc/usbtest.c Thu Jul 17 17:04:36 2003 +++ b/drivers/usb/misc/usbtest.c Thu Jul 17 17:04:36 2003 @@ -47,6 +47,7 @@ const char *name; u8 ep_in; /* bulk/intr source */ u8 ep_out; /* bulk/intr sink */ + unsigned autoconf : 1; int alt; }; @@ -78,6 +79,61 @@ /*-------------------------------------------------------------------------*/ +static int +get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf) +{ + int tmp; + struct usb_host_interface *alt; + struct usb_host_endpoint *in, *out; + struct usb_device *udev; + + for (tmp = 0; tmp < intf->max_altsetting; tmp++) { + unsigned ep; + + in = out = 0; + alt = intf->altsetting + tmp; + + /* take the first altsetting with in-bulk + out-bulk; + * ignore other endpoints and altsetttings. + */ + for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { + struct usb_host_endpoint *e; + + e = alt->endpoint + ep; + if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK) + continue; + if (e->desc.bEndpointAddress & USB_DIR_IN) { + if (!in) + in = e; + } else { + if (!out) + out = e; + } + if (in && out) + goto found; + } + } + return -EINVAL; + +found: + udev = testdev_to_usbdev (dev); + if (alt->desc.bAlternateSetting != 0) { + tmp = usb_set_interface (udev, + alt->desc.bInterfaceNumber, + alt->desc.bAlternateSetting); + if (tmp < 0) + return tmp; + } + + dev->in_pipe = usb_rcvbulkpipe (udev, + in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + dev->out_pipe = usb_sndbulkpipe (udev, + out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + return 0; +} + +/*-------------------------------------------------------------------------*/ + /* Support for testing basic non-queued I/O streams. * * These just package urbs as requests that can be easily canceled. @@ -1275,14 +1331,26 @@ wtest = " intr-out"; } } else { - if (info->ep_in) { - dev->in_pipe = usb_rcvbulkpipe (udev, info->ep_in); - rtest = " bulk-in"; + if (info->autoconf) { + int status; + + status = get_endpoints (dev, intf); + if (status < 0) { + dbg ("couldn't get endpoints, %d\n", status); + return status; + } + } else { + if (info->ep_in) + dev->in_pipe = usb_rcvbulkpipe (udev, + info->ep_in); + if (info->ep_out) + dev->out_pipe = usb_sndbulkpipe (udev, + info->ep_out); } - if (info->ep_out) { - dev->out_pipe = usb_sndbulkpipe (udev, info->ep_out); + if (dev->in_pipe) + rtest = " bulk-in"; + if (dev->out_pipe) wtest = " bulk-out"; - } } usb_set_intfdata (intf, dev); @@ -1336,11 +1404,6 @@ }; /* ezusb family device with dedicated usb test firmware, - * or a peripheral running Linux and 'zero.c' test firmware. - * - * FIXME usbtest should read the descriptors, since compatible - * test firmware might run on hardware (pxa250 for one) that - * can't configure an ep2in-bulk. */ static struct usbtest_info fw_info = { .name = "usb test device", @@ -1349,10 +1412,20 @@ .alt = 0, }; +/* peripheral running Linux and 'zero.c' test firmware, or + * its user-mode cousin. different versions of this use + * different hardware with the same vendor/product codes. + * host side MUST rely on the endpoint descriptors. + */ +static struct usbtest_info gz_info = { + .name = "Linux gadget zero", + .autoconf = 1, + .alt = 0, +}; + static struct usbtest_info um_info = { - .name = "user mode test driver", - .ep_in = 7, - .ep_out = 3, + .name = "Linux user mode test driver", + .autoconf = 1, .alt = -1, }; @@ -1418,7 +1491,7 @@ /* "Gadget Zero" firmware runs under Linux */ { USB_DEVICE (0x0525, 0xa4a0), - .driver_info = (unsigned long) &fw_info, + .driver_info = (unsigned long) &gz_info, }, /* so does a user-mode variant */