Commit 23cd1385 authored by Remy Bohmer's avatar Remy Bohmer
Browse files

Integrate USB gadget layer and USB CDC driver layer



Derived from Linux kernel 2.6.27
Signed-off-by: default avatarThomas Smits <ts.smits@gmail.com>
Signed-off-by: default avatarRemy Bohmer <linux@bohmer.net>
parent 70fccb3f
......@@ -25,6 +25,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libusb_gadget.a
# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE
ifdef CONFIG_USB_DEVICE
COBJS-y += core.o
COBJS-y += ep0.o
......@@ -34,6 +35,8 @@ COBJS-$(CONFIG_MPC885_FAMILY) += mpc8xx_udc.o
COBJS-$(CONFIG_PXA27X) += pxa27x_udc.o
COBJS-$(CONFIG_SPEARUDC) += spr_udc.o
endif
# new USB gadget layer dependencies
COBJS-$(CONFIG_USB_ETHER) += ether.o epautoconf.o config.o usbstring.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
......
/*
* usb/gadget/config.c -- simplify building config descriptors
*
* Copyright (C) 2003 David Brownell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
* Remy Bohmer <linux@bohmer.net>
*/
#include <common.h>
#include <asm/errno.h>
#include <linux/list.h>
#include <linux/string.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
* @buf: Buffer to be filled
* @buflen: Size of buf
* @src: Array of descriptor pointers, terminated by null pointer.
*
* Copies descriptors into the buffer, returning the length or a
* negative error code if they can't all be copied. Useful when
* assembling descriptors for an associated set of interfaces used
* as part of configuring a composite device; or in other cases where
* sets of descriptors need to be marshaled.
*/
int
usb_descriptor_fillbuf(void *buf, unsigned buflen,
const struct usb_descriptor_header **src)
{
u8 *dest = buf;
if (!src)
return -EINVAL;
/* fill buffer from src[] until null descriptor ptr */
for (; NULL != *src; src++) {
unsigned len = (*src)->bLength;
if (len > buflen)
return -EINVAL;
memcpy(dest, *src, len);
buflen -= len;
dest += len;
}
return dest - (u8 *)buf;
}
/**
* usb_gadget_config_buf - builts a complete configuration descriptor
* @config: Header for the descriptor, including characteristics such
* as power requirements and number of interfaces.
* @desc: Null-terminated vector of pointers to the descriptors (interface,
* endpoint, etc) defining all functions in this device configuration.
* @buf: Buffer for the resulting configuration descriptor.
* @length: Length of buffer. If this is not big enough to hold the
* entire configuration descriptor, an error code will be returned.
*
* This copies descriptors into the response buffer, building a descriptor
* for that configuration. It returns the buffer length or a negative
* status code. The config.wTotalLength field is set to match the length
* of the result, but other descriptor fields (including power usage and
* interface count) must be set by the caller.
*
* Gadget drivers could use this when constructing a config descriptor
* in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the
* resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
*/
int usb_gadget_config_buf(
const struct usb_config_descriptor *config,
void *buf,
unsigned length,
const struct usb_descriptor_header **desc
)
{
struct usb_config_descriptor *cp = buf;
int len;
/* config descriptor first */
if (length < USB_DT_CONFIG_SIZE || !desc)
return -EINVAL;
*cp = *config;
/* then interface/endpoint/class/vendor/... */
len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
length - USB_DT_CONFIG_SIZE, desc);
if (len < 0)
return len;
len += USB_DT_CONFIG_SIZE;
if (len > 0xffff)
return -EINVAL;
/* patch up the config descriptor */
cp->bLength = USB_DT_CONFIG_SIZE;
cp->bDescriptorType = USB_DT_CONFIG;
cp->wTotalLength = cpu_to_le16(len);
cp->bmAttributes |= USB_CONFIG_ATT_ONE;
return len;
}
/*
* epautoconf.c -- endpoint autoconfiguration for usb gadget drivers
*
* Copyright (C) 2004 David Brownell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
* Remy Bohmer <linux@bohmer.net>
*/
#include <common.h>
#include <linux/usb/ch9.h>
#include <asm/errno.h>
#include <linux/usb/gadget.h>
#include "gadget_chips.h"
#define isdigit(c) ('0' <= (c) && (c) <= '9')
/* we must assign addresses for configurable endpoints (like net2280) */
static unsigned epnum;
// #define MANY_ENDPOINTS
#ifdef MANY_ENDPOINTS
/* more than 15 configurable endpoints */
static unsigned in_epnum;
#endif
/*
* This should work with endpoints from controller drivers sharing the
* same endpoint naming convention. By example:
*
* - ep1, ep2, ... address is fixed, not direction or type
* - ep1in, ep2out, ... address and direction are fixed, not type
* - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
* - ep1in-bulk, ep2out-iso, ... all three are fixed
* - ep-* ... no functionality restrictions
*
* Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
* Less common restrictions are implied by gadget_is_*().
*
* NOTE: each endpoint is unidirectional, as specified by its USB
* descriptor; and isn't specific to a configuration or altsetting.
*/
static int
ep_matches (
struct usb_gadget *gadget,
struct usb_ep *ep,
struct usb_endpoint_descriptor *desc
)
{
u8 type;
const char *tmp;
u16 max;
/* endpoint already claimed? */
if (NULL != ep->driver_data)
return 0;
/* only support ep0 for portable CONTROL traffic */
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
if (USB_ENDPOINT_XFER_CONTROL == type)
return 0;
/* some other naming convention */
if ('e' != ep->name[0])
return 0;
/* type-restriction: "-iso", "-bulk", or "-int".
* direction-restriction: "in", "out".
*/
if ('-' != ep->name[2]) {
tmp = strrchr (ep->name, '-');
if (tmp) {
switch (type) {
case USB_ENDPOINT_XFER_INT:
/* bulk endpoints handle interrupt transfers,
* except the toggle-quirky iso-synch kind
*/
if ('s' == tmp[2]) // == "-iso"
return 0;
/* for now, avoid PXA "interrupt-in";
* it's documented as never using DATA1.
*/
if (gadget_is_pxa (gadget)
&& 'i' == tmp [1])
return 0;
break;
case USB_ENDPOINT_XFER_BULK:
if ('b' != tmp[1]) // != "-bulk"
return 0;
break;
case USB_ENDPOINT_XFER_ISOC:
if ('s' != tmp[2]) // != "-iso"
return 0;
}
} else {
tmp = ep->name + strlen (ep->name);
}
/* direction-restriction: "..in-..", "out-.." */
tmp--;
if (!isdigit (*tmp)) {
if (desc->bEndpointAddress & USB_DIR_IN) {
if ('n' != *tmp)
return 0;
} else {
if ('t' != *tmp)
return 0;
}
}
}
/* endpoint maxpacket size is an input parameter, except for bulk
* where it's an output parameter representing the full speed limit.
* the usb spec fixes high speed bulk maxpacket at 512 bytes.
*/
max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
switch (type) {
case USB_ENDPOINT_XFER_INT:
/* INT: limit 64 bytes full speed, 1024 high speed */
if (!gadget->is_dualspeed && max > 64)
return 0;
/* FALLTHROUGH */
case USB_ENDPOINT_XFER_ISOC:
/* ISO: limit 1023 bytes full speed, 1024 high speed */
if (ep->maxpacket < max)
return 0;
if (!gadget->is_dualspeed && max > 1023)
return 0;
/* BOTH: "high bandwidth" works only at high speed */
if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) {
if (!gadget->is_dualspeed)
return 0;
/* configure your hardware with enough buffering!! */
}
break;
}
/* MATCH!! */
/* report address */
if (isdigit (ep->name [2])) {
u8 num = simple_strtol (&ep->name [2], NULL, 10);
desc->bEndpointAddress |= num;
#ifdef MANY_ENDPOINTS
} else if (desc->bEndpointAddress & USB_DIR_IN) {
if (++in_epnum > 15)
return 0;
desc->bEndpointAddress = USB_DIR_IN | in_epnum;
#endif
} else {
if (++epnum > 15)
return 0;
desc->bEndpointAddress |= epnum;
}
/* report (variable) full speed bulk maxpacket */
if (USB_ENDPOINT_XFER_BULK == type) {
int size = ep->maxpacket;
/* min() doesn't work on bitfields with gcc-3.5 */
if (size > 64)
size = 64;
desc->wMaxPacketSize = cpu_to_le16(size);
}
return 1;
}
static struct usb_ep *
find_ep (struct usb_gadget *gadget, const char *name)
{
struct usb_ep *ep;
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
if (0 == strcmp (ep->name, name))
return ep;
}
return NULL;
}
/**
* usb_ep_autoconfig - choose an endpoint matching the descriptor
* @gadget: The device to which the endpoint must belong.
* @desc: Endpoint descriptor, with endpoint direction and transfer mode
* initialized. For periodic transfers, the maximum packet
* size must also be initialized. This is modified on success.
*
* By choosing an endpoint to use with the specified descriptor, this
* routine simplifies writing gadget drivers that work with multiple
* USB device controllers. The endpoint would be passed later to
* usb_ep_enable(), along with some descriptor.
*
* That second descriptor won't always be the same as the first one.
* For example, isochronous endpoints can be autoconfigured for high
* bandwidth, and then used in several lower bandwidth altsettings.
* Also, high and full speed descriptors will be different.
*
* Be sure to examine and test the results of autoconfiguration on your
* hardware. This code may not make the best choices about how to use the
* USB controller, and it can't know all the restrictions that may apply.
* Some combinations of driver and hardware won't be able to autoconfigure.
*
* On success, this returns an un-claimed usb_ep, and modifies the endpoint
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
* is initialized as if the endpoint were used at full speed. To prevent
* the endpoint from being returned by a later autoconfig call, claim it
* by assigning ep->driver_data to some non-null value.
*
* On failure, this returns a null endpoint descriptor.
*/
struct usb_ep * usb_ep_autoconfig (
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc
)
{
struct usb_ep *ep;
u8 type;
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
/* First, apply chip-specific "best usage" knowledge.
* This might make a good usb_gadget_ops hook ...
*/
if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
/* ep-e, ep-f are PIO with only 64 byte fifos */
ep = find_ep (gadget, "ep-e");
if (ep && ep_matches (gadget, ep, desc))
return ep;
ep = find_ep (gadget, "ep-f");
if (ep && ep_matches (gadget, ep, desc))
return ep;
} else if (gadget_is_goku (gadget)) {
if (USB_ENDPOINT_XFER_INT == type) {
/* single buffering is enough */
ep = find_ep (gadget, "ep3-bulk");
if (ep && ep_matches (gadget, ep, desc))
return ep;
} else if (USB_ENDPOINT_XFER_BULK == type
&& (USB_DIR_IN & desc->bEndpointAddress)) {
/* DMA may be available */
ep = find_ep (gadget, "ep2-bulk");
if (ep && ep_matches (gadget, ep, desc))
return ep;
}
} else if (gadget_is_sh (gadget) && USB_ENDPOINT_XFER_INT == type) {
/* single buffering is enough; maybe 8 byte fifo is too */
ep = find_ep (gadget, "ep3in-bulk");
if (ep && ep_matches (gadget, ep, desc))
return ep;
} else if (gadget_is_mq11xx (gadget) && USB_ENDPOINT_XFER_INT == type) {
ep = find_ep (gadget, "ep1-bulk");
if (ep && ep_matches (gadget, ep, desc))
return ep;
}
/* Second, look at endpoints until an unclaimed one looks usable */
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
if (ep_matches (gadget, ep, desc))
return ep;
}
/* Fail */
return NULL;
}
/**
* usb_ep_autoconfig_reset - reset endpoint autoconfig state
* @gadget: device for which autoconfig state will be reset
*
* Use this for devices where one configuration may need to assign
* endpoint resources very differently from the next one. It clears
* state such as ep->driver_data and the record of assigned endpoints
* used by usb_ep_autoconfig().
*/
void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
{
struct usb_ep *ep;
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
ep->driver_data = NULL;
}
#ifdef MANY_ENDPOINTS
in_epnum = 0;
#endif
epnum = 0;
}
This diff is collapsed.
/*
* USB device controllers have lots of quirks. Use these macros in
* gadget drivers or other code that needs to deal with them, and which
* autoconfigures instead of using early binding to the hardware.
*
* This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
* some config file that gets updated as new hardware is supported.
* (And avoiding all runtime comparisons in typical one-choice configs!)
*
* NOTE: some of these controller drivers may not be available yet.
* Some are available on 2.4 kernels; several are available, but not
* yet pushed in the 2.6 mainline tree.
*
* Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
* Remy Bohmer <linux@bohmer.net>
*/
#ifdef CONFIG_USB_GADGET_NET2280
#define gadget_is_net2280(g) !strcmp("net2280", (g)->name)
#else
#define gadget_is_net2280(g) 0
#endif
#ifdef CONFIG_USB_GADGET_AMD5536UDC
#define gadget_is_amd5536udc(g) !strcmp("amd5536udc", (g)->name)
#else
#define gadget_is_amd5536udc(g) 0
#endif
#ifdef CONFIG_USB_GADGET_DUMMY_HCD
#define gadget_is_dummy(g) !strcmp("dummy_udc", (g)->name)
#else
#define gadget_is_dummy(g) 0
#endif
#ifdef CONFIG_USB_GADGET_PXA2XX
#define gadget_is_pxa(g) !strcmp("pxa2xx_udc", (g)->name)
#else
#define gadget_is_pxa(g) 0
#endif
#ifdef CONFIG_USB_GADGET_GOKU
#define gadget_is_goku(g) !strcmp("goku_udc", (g)->name)
#else
#define gadget_is_goku(g) 0
#endif
/* SH3 UDC -- not yet ported 2.4 --> 2.6 */
#ifdef CONFIG_USB_GADGET_SUPERH
#define gadget_is_sh(g) !strcmp("sh_udc", (g)->name)
#else
#define gadget_is_sh(g) 0
#endif
/* not yet stable on 2.6 (would help "original Zaurus") */
#ifdef CONFIG_USB_GADGET_SA1100
#define gadget_is_sa1100(g) !strcmp("sa1100_udc", (g)->name)
#else
#define gadget_is_sa1100(g) 0
#endif
#ifdef CONFIG_USB_GADGET_LH7A40X
#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name)
#else
#define gadget_is_lh7a40x(g) 0
#endif
/* handhelds.org tree (?) */
#ifdef CONFIG_USB_GADGET_MQ11XX
#define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name)
#else
#define gadget_is_mq11xx(g) 0
#endif
#ifdef CONFIG_USB_GADGET_OMAP
#define gadget_is_omap(g) !strcmp("omap_udc", (g)->name)
#else
#define gadget_is_omap(g) 0
#endif
/* not yet ported 2.4 --> 2.6 */
#ifdef CONFIG_USB_GADGET_N9604
#define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name)
#else
#define gadget_is_n9604(g) 0
#endif
/* various unstable versions available */
#ifdef CONFIG_USB_GADGET_PXA27X
#define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name)
#else
#define gadget_is_pxa27x(g) 0
#endif
#ifdef CONFIG_USB_GADGET_ATMEL_USBA
#define gadget_is_atmel_usba(g) !strcmp("atmel_usba_udc", (g)->name)
#else
#define gadget_is_atmel_usba(g) 0
#endif
#ifdef CONFIG_USB_GADGET_S3C2410
#define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name)
#else
#define gadget_is_s3c2410(g) 0
#endif
#ifdef CONFIG_USB_GADGET_AT91
#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
#else
#define gadget_is_at91(g) 0
#endif
/* status unclear */
#ifdef CONFIG_USB_GADGET_IMX
#define gadget_is_imx(g) !strcmp("imx_udc", (g)->name)
#else
#define gadget_is_imx(g) 0
#endif
#ifdef CONFIG_USB_GADGET_FSL_USB2
#define gadget_is_fsl_usb2(g) !strcmp("fsl-usb2-udc", (g)->name)
#else
#define gadget_is_fsl_usb2(g) 0
#endif
/* Mentor high speed function controller */
/* from Montavista kernel (?) */
#ifdef CONFIG_USB_GADGET_MUSBHSFC
#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name)
#else
#define gadget_is_musbhsfc(g) 0
#endif
/* Mentor high speed "dual role" controller, in peripheral role */
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
#define gadget_is_musbhdrc(g) !strcmp("musb_hdrc", (g)->name)
#else
#define gadget_is_musbhdrc(g) 0
#endif
/* from Montavista kernel (?) */
#ifdef CONFIG_USB_GADGET_MPC8272
#define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name)
#else
#define gadget_is_mpc8272(g) 0
#endif
#ifdef CONFIG_USB_GADGET_M66592
#define gadget_is_m66592(g) !strcmp("m66592_udc", (g)->name)
#else
#define gadget_is_m66592(g) 0
#endif
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
// ...
/**
* usb_gadget_controller_number - support bcdDevice id convention
* @gadget: the controller being driven
*
* Return a 2-digit BCD value associated with the peripheral controller,
* suitable for use as part of a bcdDevice value, or a negative error code.
*
* NOTE: this convention is purely optional, and has no meaning in terms of
* any USB specification. If you want to use a different convention in your
* gadget driver firmware -- maybe a more formal revision ID -- feel free.
*
* Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
* to change their behavior accordingly. For example it might help avoiding
* some chip bug.
*/
static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
{
if (gadget_is_net2280(gadget))
return 0x01;
else if (gadget_is_dummy(gadget))
return 0x02;
else if (gadget_is_pxa(gadget))
return 0x03;
else if (gadget_is_sh(gadget))
return 0x04;
else if (gadget_is_sa1100(gadget))