Commit 71640f89 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: gadget zero does endpoint autoconfig

Here's where all those preceding autoconfig patches start
to fit together:  one gadget driver gets rid of almost all
the controller-specific #ifdeffery.

Two of the other gadget drivers can do the same thing,
and just as easily:  file storage, and serial.  (I'll
hope their maintainers do those changes though.)

The "ether.c" gadget driver is a lot more complicated to
do this way since it has to cope with some differences
by switching to alternate protocols (CDC Ethernet vs
a subset) and soon be able to handle RNDIS.  So that'll
be a while yet.


Gadget Zero learns to autoconfigure.

    - Gets rid of remaining controller-specific #ifdeffery.  Now
      hardware choices can be made at run time too (not just
      compile time).

    - Simplifies its use of the "DEBUG" CPP symbol.

    - Force device to report itself consistently as self-powered.
parent 4992d46a
...@@ -8,7 +8,7 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o ...@@ -8,7 +8,7 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o
# #
# USB gadget drivers # USB gadget drivers
# #
g_zero-objs := zero.o usbstring.o config.o g_zero-objs := zero.o usbstring.o config.o epautoconf.o
g_ether-objs := ether.o usbstring.o config.o g_ether-objs := ether.o usbstring.o config.o
g_serial-objs := serial.o usbstring.o g_serial-objs := serial.o usbstring.o
gadgetfs-objs := inode.o usbstring.o gadgetfs-objs := inode.o usbstring.o
......
...@@ -89,10 +89,12 @@ ...@@ -89,10 +89,12 @@
#include <linux/usb_ch9.h> #include <linux/usb_ch9.h>
#include <linux/usb_gadget.h> #include <linux/usb_gadget.h>
#include "gadget_chips.h"
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define DRIVER_VERSION "Bastille Day 2003" #define DRIVER_VERSION "St Patrick's Day 2004"
static const char shortname [] = "zero"; static const char shortname [] = "zero";
static const char longname [] = "Gadget Zero"; static const char longname [] = "Gadget Zero";
...@@ -105,100 +107,12 @@ static const char loopback [] = "loop input to output"; ...@@ -105,100 +107,12 @@ static const char loopback [] = "loop input to output";
/* /*
* driver assumes self-powered hardware, and * driver assumes self-powered hardware, and
* has no way for users to trigger remote wakeup. * has no way for users to trigger remote wakeup.
*/
/*
* hardware-specific configuration, controlled by which device
* controller driver was configured.
*
* CHIP ... hardware identifier
* DRIVER_VERSION_NUM ... alerts the host side driver to differences
* EP_*_NAME ... which endpoints do we use for which purpose?
* EP_*_NUM ... numbers for them (often limited by hardware)
*
* add other defines for other portability issues, like hardware that
* for some reason doesn't handle full speed bulk maxpacket of 64.
*/
/*
* DRIVER_VERSION_NUM 0x0000 (?): Martin Diehl's ezusb an21/fx code
*/
/*
* NetChip 2280, PCI based.
* *
* This has half a dozen configurable endpoints, four with dedicated * this version autoconfigures as much as possible,
* DMA channels to manage their FIFOs. It supports high speed. * which is reasonable for most "bulk-only" drivers.
* Those endpoints can be arranged in any desired configuration.
*/ */
#if defined(CONFIG_USB_GADGET_NET2280) || defined(CONFIG_USB_GADGET_DUMMY_HCD) static const char *EP_IN_NAME; /* source */
#define CHIP "net2280" static const char *EP_OUT_NAME; /* sink */
#define DRIVER_VERSION_NUM 0x0101
static const char EP_OUT_NAME [] = "ep-a";
#define EP_OUT_NUM 2
static const char EP_IN_NAME [] = "ep-b";
#define EP_IN_NUM 2
#endif
/*
* PXA-2xx UDC: widely used in second gen Linux-capable PDAs.
*
* This has fifteen fixed-function full speed endpoints, and it
* can support all USB transfer types.
*
* These supports three or four configurations, with fixed numbers.
* The hardware interprets SET_INTERFACE, net effect is that you
* can't use altsettings or reset the interfaces independently.
* So stick to a single interface.
*/
#ifdef CONFIG_USB_GADGET_PXA2XX
#define CHIP "pxa2xx"
#define DRIVER_VERSION_NUM 0x0103
static const char EP_OUT_NAME [] = "ep12out-bulk";
#define EP_OUT_NUM 12
static const char EP_IN_NAME [] = "ep11in-bulk";
#define EP_IN_NUM 11
#endif
/*
* SA-1100 UDC: widely used in first gen Linux-capable PDAs.
*
* This has only two fixed function endpoints, which can only
* be used for bulk (or interrupt) transfers. (Plus control.)
*
* Since it can't flush its TX fifos without disabling the UDC,
* the current configuration or altsettings can't change except
* in special situations. So this is a case of "choose it right
* during enumeration" ...
*/
#ifdef CONFIG_USB_GADGET_SA1100
#define CHIP "sa1100"
#define DRIVER_VERSION_NUM 0x0105
static const char EP_OUT_NAME [] = "ep1out-bulk";
#define EP_OUT_NUM 1
static const char EP_IN_NAME [] = "ep2in-bulk";
#define EP_IN_NUM 2
#endif
/*
* Toshiba TC86C001 ("Goku-S") UDC
*
* This has three semi-configurable full speed bulk/interrupt endpoints.
*/
#ifdef CONFIG_USB_GADGET_GOKU
#define CHIP "goku"
#define DRIVER_VERSION_NUM 0x0106
static const char EP_OUT_NAME [] = "ep1-bulk";
#define EP_OUT_NUM 1
static const char EP_IN_NAME [] = "ep2-bulk";
#define EP_IN_NUM 2
#endif
/*-------------------------------------------------------------------------*/
#ifndef EP_OUT_NUM
# error Configure some USB peripheral controller driver!
#endif
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -222,20 +136,19 @@ struct zero_dev { ...@@ -222,20 +136,19 @@ struct zero_dev {
dev_printk(level , &(d)->gadget->dev , fmt , ## args) dev_printk(level , &(d)->gadget->dev , fmt , ## args)
#ifdef DEBUG #ifdef DEBUG
#undef DEBUG #define DBG(dev,fmt,args...) \
#define DEBUG(dev,fmt,args...) \
xprintk(dev , KERN_DEBUG , fmt , ## args) xprintk(dev , KERN_DEBUG , fmt , ## args)
#else #else
#define DEBUG(dev,fmt,args...) \ #define DBG(dev,fmt,args...) \
do { } while (0) do { } while (0)
#endif /* DEBUG */ #endif /* DEBUG */
#ifdef VERBOSE #ifdef VERBOSE
#define VDEBUG DEBUG #define VDBG DBG
#else #else
#define VDEBUG(dev,fmt,args...) \ #define VDBG(dev,fmt,args...) \
do { } while (0) do { } while (0)
#endif /* DEBUG */ #endif /* VERBOSE */
#define ERROR(dev,fmt,args...) \ #define ERROR(dev,fmt,args...) \
xprintk(dev , KERN_ERR , fmt , ## args) xprintk(dev , KERN_ERR , fmt , ## args)
...@@ -305,7 +218,6 @@ device_desc = { ...@@ -305,7 +218,6 @@ device_desc = {
.idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM), .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM), .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
.bcdDevice = __constant_cpu_to_le16 (DRIVER_VERSION_NUM),
.iManufacturer = STRING_MANUFACTURER, .iManufacturer = STRING_MANUFACTURER,
.iProduct = STRING_PRODUCT, .iProduct = STRING_PRODUCT,
.iSerialNumber = STRING_SERIAL, .iSerialNumber = STRING_SERIAL,
...@@ -362,24 +274,22 @@ loopback_intf = { ...@@ -362,24 +274,22 @@ loopback_intf = {
/* two full speed bulk endpoints; their use is config-dependent */ /* two full speed bulk endpoints; their use is config-dependent */
static const struct usb_endpoint_descriptor static struct usb_endpoint_descriptor
fs_source_desc = { fs_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_IN_NUM | USB_DIR_IN, .bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16 (64),
}; };
static const struct usb_endpoint_descriptor static struct usb_endpoint_descriptor
fs_sink_desc = { fs_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP_OUT_NUM, .bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16 (64),
}; };
static const struct usb_descriptor_header *fs_source_sink_function [] = { static const struct usb_descriptor_header *fs_source_sink_function [] = {
...@@ -643,7 +553,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -643,7 +553,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
case -ECONNABORTED: /* hardware forced ep reset */ case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */ case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */ case -ESHUTDOWN: /* disconnect from host */
VDEBUG (dev, "%s gone (%d), %d/%d\n", ep->name, status, VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
req->actual, req->length); req->actual, req->length);
if (ep == dev->out_ep) if (ep == dev->out_ep)
check_read_data (dev, ep, req); check_read_data (dev, ep, req);
...@@ -656,7 +566,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req) ...@@ -656,7 +566,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
*/ */
default: default:
#if 1 #if 1
DEBUG (dev, "%s complete --> %d, %d/%d\n", ep->name, DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
status, req->actual, req->length); status, req->actual, req->length);
#endif #endif
case -EREMOTEIO: /* short read */ case -EREMOTEIO: /* short read */
...@@ -747,7 +657,7 @@ set_source_sink_config (struct zero_dev *dev, int gfp_flags) ...@@ -747,7 +657,7 @@ set_source_sink_config (struct zero_dev *dev, int gfp_flags)
break; break;
} }
if (result == 0) if (result == 0)
DEBUG (dev, "buflen %d\n", buflen); DBG (dev, "buflen %d\n", buflen);
/* caller is responsible for cleanup on error */ /* caller is responsible for cleanup on error */
return result; return result;
...@@ -858,14 +768,14 @@ set_loopback_config (struct zero_dev *dev, int gfp_flags) ...@@ -858,14 +768,14 @@ set_loopback_config (struct zero_dev *dev, int gfp_flags)
req->complete = loopback_complete; req->complete = loopback_complete;
result = usb_ep_queue (ep, req, GFP_ATOMIC); result = usb_ep_queue (ep, req, GFP_ATOMIC);
if (result) if (result)
DEBUG (dev, "%s queue req --> %d\n", DBG (dev, "%s queue req --> %d\n",
ep->name, result); ep->name, result);
} else } else
result = -ENOMEM; result = -ENOMEM;
} }
} }
if (result == 0) if (result == 0)
DEBUG (dev, "qlen %d, buflen %d\n", qlen, buflen); DBG (dev, "qlen %d, buflen %d\n", qlen, buflen);
/* caller is responsible for cleanup on error */ /* caller is responsible for cleanup on error */
return result; return result;
...@@ -878,7 +788,7 @@ static void zero_reset_config (struct zero_dev *dev) ...@@ -878,7 +788,7 @@ static void zero_reset_config (struct zero_dev *dev)
if (dev->config == 0) if (dev->config == 0)
return; return;
DEBUG (dev, "reset config\n"); DBG (dev, "reset config\n");
/* just disable endpoints, forcing completion of pending i/o. /* just disable endpoints, forcing completion of pending i/o.
* all our completion handlers free their requests in this case. * all our completion handlers free their requests in this case.
...@@ -913,13 +823,11 @@ zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags) ...@@ -913,13 +823,11 @@ zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
if (number == dev->config) if (number == dev->config)
return 0; return 0;
#ifdef CONFIG_USB_GADGET_SA1100 if (gadget_is_sa1100 (gadget) && dev->config) {
if (dev->config) {
/* tx fifo is full, but we can't clear it...*/ /* tx fifo is full, but we can't clear it...*/
INFO (dev, "can't change configurations\n"); INFO (dev, "can't change configurations\n");
return -ESPIPE; return -ESPIPE;
} }
#endif
zero_reset_config (dev); zero_reset_config (dev);
switch (number) { switch (number) {
...@@ -963,7 +871,7 @@ zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags) ...@@ -963,7 +871,7 @@ zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req) static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
{ {
if (req->status || req->actual != req->length) if (req->status || req->actual != req->length)
DEBUG ((struct zero_dev *) ep->driver_data, DBG ((struct zero_dev *) ep->driver_data,
"setup complete --> %d, %d/%d\n", "setup complete --> %d, %d/%d\n",
req->status, req->actual, req->length); req->status, req->actual, req->length);
} }
...@@ -1111,7 +1019,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1111,7 +1019,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
default: default:
unknown: unknown:
VDEBUG (dev, VDBG (dev,
"unknown control req%02x.%02x v%04x i%04x l%d\n", "unknown control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest, ctrl->bRequestType, ctrl->bRequest,
ctrl->wValue, ctrl->wIndex, ctrl->wLength); ctrl->wValue, ctrl->wIndex, ctrl->wLength);
...@@ -1122,7 +1030,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1122,7 +1030,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
req->length = value; req->length = value;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) { if (value < 0) {
DEBUG (dev, "ep_queue --> %d\n", value); DBG (dev, "ep_queue --> %d\n", value);
req->status = 0; req->status = 0;
zero_setup_complete (gadget->ep0, req); zero_setup_complete (gadget->ep0, req);
} }
...@@ -1159,7 +1067,7 @@ zero_unbind (struct usb_gadget *gadget) ...@@ -1159,7 +1067,7 @@ zero_unbind (struct usb_gadget *gadget)
{ {
struct zero_dev *dev = get_gadget_data (gadget); struct zero_dev *dev = get_gadget_data (gadget);
DEBUG (dev, "unbind\n"); DBG (dev, "unbind\n");
/* we've already been disconnected ... no i/o is active */ /* we've already been disconnected ... no i/o is active */
if (dev->req) if (dev->req)
...@@ -1172,7 +1080,70 @@ static int ...@@ -1172,7 +1080,70 @@ static int
zero_bind (struct usb_gadget *gadget) zero_bind (struct usb_gadget *gadget)
{ {
struct zero_dev *dev; struct zero_dev *dev;
struct usb_ep *ep;
/* Bulk-only drivers like this one SHOULD be able to
* autoconfigure on any sane usb controller driver,
* but there may also be important quirks to address.
*/
usb_ep_autoconfig_reset (gadget);
ep = usb_ep_autoconfig (gadget, &fs_source_desc);
if (!ep) {
autoconf_fail:
printk (KERN_ERR "%s: can't autoconfigure on %s\n",
shortname, gadget->name);
return -ENODEV;
}
EP_IN_NAME = ep->name;
ep->driver_data = ep; /* claim */
ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
if (!ep)
goto autoconf_fail;
EP_OUT_NAME = ep->name;
ep->driver_data = ep; /* claim */
/*
* DRIVER POLICY CHOICE: you may want to do this differently.
* One thing to avoid is reusing a bcdDevice revision code
* with different host-visible configurations or behavior
* restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
*/
if (gadget_is_net2280 (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
} else if (gadget_is_pxa (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
#if 0
} else if (gadget_is_sh(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
/* SH has only one configuration; see "loopdefault" */
device_desc.bNumConfigurations = 1;
/* FIXME make 1 == default.bConfigurationValue */
#endif
} else if (gadget_is_sa1100 (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
} else if (gadget_is_goku (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
} else if (gadget_is_mq11xx (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
} else if (gadget_is_omap (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
} else {
/* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware.
* so warn about unrcognized controllers, don't panic.
*
* things like configuration and altsetting numbering
* can need hardware-specific attention though.
*/
printk (KERN_WARNING "%s: controller '%s' not recognized\n",
shortname, gadget->name);
device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
}
/* ok, we made sense of the hardware ... */
dev = kmalloc (sizeof *dev, SLAB_KERNEL); dev = kmalloc (sizeof *dev, SLAB_KERNEL);
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
...@@ -1203,6 +1174,8 @@ zero_bind (struct usb_gadget *gadget) ...@@ -1203,6 +1174,8 @@ zero_bind (struct usb_gadget *gadget)
hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
#endif #endif
usb_gadget_set_selfpowered (gadget);
gadget->ep0->driver_data = dev; gadget->ep0->driver_data = dev;
INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname); INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment