From 0eb44cec07715a734c8d5d52fbb433e0287bc5d1 Mon Sep 17 00:00:00 2001 From: Thomas Kunze Date: Mon, 20 Oct 2008 15:16:07 +0200 Subject: linux-rp_2.6.26: add patch for collie usb --- packages/linux/linux-rp-2.6.26/defconfig-collie | 58 +- .../linux/linux-rp-2.6.26/usb-gadget27bp.patch | 26674 +++++++++++++++++++ packages/linux/linux-rp_2.6.26.bb | 3 +- 3 files changed, 26728 insertions(+), 7 deletions(-) create mode 100644 packages/linux/linux-rp-2.6.26/usb-gadget27bp.patch (limited to 'packages/linux') diff --git a/packages/linux/linux-rp-2.6.26/defconfig-collie b/packages/linux/linux-rp-2.6.26/defconfig-collie index e21cc21da2..e80885f332 100644 --- a/packages/linux/linux-rp-2.6.26/defconfig-collie +++ b/packages/linux/linux-rp-2.6.26/defconfig-collie @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.26 -# Fri Oct 17 18:46:51 2008 +# Mon Oct 20 01:48:37 2008 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -845,7 +845,13 @@ CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set # CONFIG_TOUCHSCREEN_TOUCHWIN is not set # CONFIG_TOUCHSCREEN_UCB1400 is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set CONFIG_INPUT_UINPUT=m # @@ -954,11 +960,11 @@ CONFIG_SSB_POSSIBLE=y # # Multimedia Capabilities Port drivers # -CONFIG_MCP=m -CONFIG_MCP_SA11X0=m -CONFIG_MCP_UCB1200=m +CONFIG_MCP=y +CONFIG_MCP_SA11X0=y +CONFIG_MCP_UCB1200=y # CONFIG_MCP_UCB1200_TS is not set -CONFIG_MCP_COLLIE_TS=m +CONFIG_MCP_COLLIE_TS=y # # Multimedia devices @@ -1044,7 +1050,47 @@ CONFIG_FONT_8x8=y # CONFIG_SOUND is not set # CONFIG_HID_SUPPORT is not set CONFIG_HID=m -# CONFIG_USB_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_AT91 is not set +CONFIG_USB_GADGET_SA1100=y +CONFIG_USB_SA1100=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=m +# CONFIG_USB_ETH_RNDIS is not set +# CONFIG_USB_ETH_NO_MDLM is not set +# CONFIG_USB_GADGETFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +CONFIG_USB_G_PRINTER=m CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set CONFIG_MMC_UNSAFE_RESUME=y diff --git a/packages/linux/linux-rp-2.6.26/usb-gadget27bp.patch b/packages/linux/linux-rp-2.6.26/usb-gadget27bp.patch new file mode 100644 index 0000000000..3c86f1a474 --- /dev/null +++ b/packages/linux/linux-rp-2.6.26/usb-gadget27bp.patch @@ -0,0 +1,26674 @@ +diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig +index 6e784d2..117d0c7 100644 +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -118,10 +118,10 @@ config USB_AMD5536UDC + config USB_GADGET_ATMEL_USBA + boolean "Atmel USBA" + select USB_GADGET_DUALSPEED +- depends on AVR32 || ARCH_AT91CAP9 ++ depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL + help + USBA is the integrated high-speed USB Device controller on +- the AT32AP700x and AT91CAP9 processors from Atmel. ++ the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel. + + config USB_ATMEL_USBA + tristate +@@ -172,7 +172,7 @@ config USB_NET2280 + default USB_GADGET + select USB_GADGET_SELECTED + +-config USB_GADGET_PXA2XX ++config USB_GADGET_PXA25X + boolean "PXA 25x or IXP 4xx" + depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX + help +@@ -184,19 +184,19 @@ config USB_GADGET_PXA2XX + zero (for control transfers). + + Say "y" to link the driver statically, or "m" to build a +- dynamically linked module called "pxa2xx_udc" and force all ++ dynamically linked module called "pxa25x_udc" and force all + gadget drivers to also be dynamically linked. + +-config USB_PXA2XX ++config USB_PXA25X + tristate +- depends on USB_GADGET_PXA2XX ++ depends on USB_GADGET_PXA25X + default USB_GADGET + select USB_GADGET_SELECTED + + # if there's only one gadget driver, using only two bulk endpoints, + # don't waste memory for the other endpoints +-config USB_PXA2XX_SMALL +- depends on USB_GADGET_PXA2XX ++config USB_PXA25X_SMALL ++ depends on USB_GADGET_PXA25X + bool + default n if USB_ETH_RNDIS + default y if USB_ZERO +@@ -284,6 +284,16 @@ config USB_LH7A40X + default USB_GADGET + select USB_GADGET_SELECTED + ++# built in ../musb along with host support ++config USB_GADGET_MUSB_HDRC ++ boolean "Inventra HDRC USB Peripheral (TI, ...)" ++ depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG) ++ select USB_GADGET_DUALSPEED ++ select USB_GADGET_SELECTED ++ help ++ This OTG-capable silicon IP is used in dual designs including ++ the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010. ++ + config USB_GADGET_OMAP + boolean "OMAP USB Device Controller" + depends on ARCH_OMAP +@@ -355,6 +365,20 @@ config USB_AT91 + depends on USB_GADGET_AT91 + default USB_GADGET + ++config USB_GADGET_SA1100 ++ boolean "SA1100 USB Device Port" ++ depends on ARCH_SA1100 ++ help ++ Say "y" to link the driver statically, or "m" to build a ++ dynamically linked module called "sa1100_udc" and force all ++ gadget drivers to also be dynamically linked. ++ ++config USB_SA1100 ++ tristate ++ depends on USB_GADGET_SA1100 ++ default USB_GADGET ++ select USB_GADGET_SELECTED ++ + config USB_GADGET_DUMMY_HCD + boolean "Dummy HCD (DEVELOPMENT)" + depends on USB=y || (USB=m && USB_GADGET=m) +@@ -504,6 +528,20 @@ config USB_ETH_RNDIS + XP, you'll need to download drivers from Microsoft's website; a URL + is given in comments found in that info file. + ++config USB_ETH_NO_MDLM ++ bool "Disable MDLM support for CDC_SUBSET" ++ depends on USB_ETH ++ default n ++ help ++ A variation on CDC_SUBSET support is used in newer kernel ++ implementations for use with a proprietary Microsoft Windows driver ++ used for example with the Zaurus linux distribution. ++ However, the MDLM extensions break the older host side drivers making ++ g_ether incompatible with older kernels. ++ ++ If you say "y" here, the Ethernet gadget driver will use the older ++ pre-MDLM extensions. ++ + config USB_GADGETFS + tristate "Gadget Filesystem (EXPERIMENTAL)" + depends on EXPERIMENTAL +@@ -586,6 +624,20 @@ config USB_G_PRINTER + For more information, see Documentation/usb/gadget_printer.txt + which includes sample code for accessing the device file. + ++config USB_CDC_COMPOSITE ++ tristate "CDC Composite Device (Ethernet and ACM)" ++ depends on NET ++ help ++ This driver provides two functions in one configuration: ++ a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link. ++ ++ This driver requires four bulk and two interrupt endpoints, ++ plus the ability to handle altsettings. Not all peripheral ++ controllers are that capable. ++ ++ Say "y" to link the driver statically, or "m" to build a ++ dynamically linked module. ++ + # put drivers that need isochronous transfer support (for audio + # or video class gadget drivers), or specific hardware, here. + +diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile +index 1235725..79a69ae 100644 +--- a/drivers/usb/gadget/Makefile ++++ b/drivers/usb/gadget/Makefile +@@ -8,7 +8,7 @@ endif + obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o + obj-$(CONFIG_USB_NET2280) += net2280.o + obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o +-obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o ++obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o + obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o + obj-$(CONFIG_USB_GOKU) += goku_udc.o + obj-$(CONFIG_USB_OMAP) += omap_udc.o +@@ -18,22 +18,27 @@ obj-$(CONFIG_USB_AT91) += at91_udc.o + obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o + obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o + obj-$(CONFIG_USB_M66592) += m66592-udc.o ++obj-$(CONFIG_USB_SA1100) += sa1100_udc.o + + # + # USB gadget drivers + # +-g_zero-objs := zero.o usbstring.o config.o epautoconf.o +-g_ether-objs := ether.o usbstring.o config.o epautoconf.o +-g_serial-objs := serial.o usbstring.o config.o epautoconf.o ++C_UTILS = composite.o usbstring.o config.o epautoconf.o ++ ++g_zero-objs := zero.o f_sourcesink.o f_loopback.o $(C_UTILS) ++g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS) ++g_serial-objs := serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS) + g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o + gadgetfs-objs := inode.o + g_file_storage-objs := file_storage.o usbstring.o config.o \ + epautoconf.o + g_printer-objs := printer.o usbstring.o config.o \ + epautoconf.o ++g_cdc-objs := cdc2.o u_ether.o f_ecm.o \ ++ u_serial.o f_acm.o $(C_UTILS) + + ifeq ($(CONFIG_USB_ETH_RNDIS),y) +- g_ether-objs += rndis.o ++ g_ether-objs += f_rndis.o rndis.o + endif + + obj-$(CONFIG_USB_ZERO) += g_zero.o +@@ -43,4 +48,5 @@ obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o + obj-$(CONFIG_USB_G_SERIAL) += g_serial.o + obj-$(CONFIG_USB_G_PRINTER) += g_printer.o + obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o ++obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o + +diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c +index f261d2a..abf8192 100644 +--- a/drivers/usb/gadget/amd5536udc.c ++++ b/drivers/usb/gadget/amd5536udc.c +@@ -44,7 +44,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -3342,7 +3341,7 @@ static int udc_probe(struct udc *dev) + spin_lock_init(&dev->lock); + dev->gadget.ops = &udc_ops; + +- strcpy(dev->gadget.dev.bus_id, "gadget"); ++ dev_set_name(&dev->gadget.dev, "gadget"); + dev->gadget.dev.release = gadget_release; + dev->gadget.name = name; + dev->gadget.name = name; +diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c +index 274c60a..a8a1de4 100644 +--- a/drivers/usb/gadget/at91_udc.c ++++ b/drivers/usb/gadget/at91_udc.c +@@ -40,16 +40,15 @@ + #include + + #include +-#include ++#include + #include + #include + #include +-#include + #include + +-#include +-#include +-#include ++#include ++#include ++#include + + #include "at91_udc.h" + +@@ -888,7 +887,7 @@ static void pullup(struct at91_udc *udc, int is_on) + at91_udp_write(udc, AT91_UDP_TXVC, 0); + if (cpu_is_at91rm9200()) + gpio_set_value(udc->board.pullup_pin, active); +- else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { ++ else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) { + u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); + + txvc |= AT91_UDP_TXVC_PUON; +@@ -906,7 +905,7 @@ static void pullup(struct at91_udc *udc, int is_on) + at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); + if (cpu_is_at91rm9200()) + gpio_set_value(udc->board.pullup_pin, !active); +- else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { ++ else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) { + u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC); + + txvc &= ~AT91_UDP_TXVC_PUON; +@@ -1687,6 +1686,19 @@ static int __init at91udc_probe(struct platform_device *pdev) + udc->board.pullup_active_low); + } + ++ /* newer chips have more FIFO memory than rm9200 */ ++ if (cpu_is_at91sam9260()) { ++ udc->ep[0].maxpacket = 64; ++ udc->ep[3].maxpacket = 64; ++ udc->ep[4].maxpacket = 512; ++ udc->ep[5].maxpacket = 512; ++ } else if (cpu_is_at91sam9261()) { ++ udc->ep[3].maxpacket = 64; ++ } else if (cpu_is_at91sam9263()) { ++ udc->ep[0].maxpacket = 64; ++ udc->ep[3].maxpacket = 64; ++ } ++ + udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1); + if (!udc->udp_baseaddr) { + retval = -ENOMEM; +diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h +index a973f2a..c65d622 100644 +--- a/drivers/usb/gadget/at91_udc.h ++++ b/drivers/usb/gadget/at91_udc.h +@@ -171,7 +171,7 @@ struct at91_request { + #endif + + #define ERR(stuff...) pr_err("udc: " stuff) +-#define WARN(stuff...) pr_warning("udc: " stuff) ++#define WARNING(stuff...) pr_warning("udc: " stuff) + #define INFO(stuff...) pr_info("udc: " stuff) + #define DBG(stuff...) pr_debug("udc: " stuff) + +diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c +index 07e5a0b..ae30ab1 100644 +--- a/drivers/usb/gadget/atmel_usba_udc.c ++++ b/drivers/usb/gadget/atmel_usba_udc.c +@@ -22,7 +22,7 @@ + #include + + #include +-#include ++#include + + #include "atmel_usba_udc.h" + +@@ -334,7 +334,7 @@ static void toggle_bias(int is_on) + + #elif defined(CONFIG_ARCH_AT91) + +-#include ++#include + + static void toggle_bias(int is_on) + { +diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c +new file mode 100644 +index 0000000..a39a4b9 +--- /dev/null ++++ b/drivers/usb/gadget/cdc2.c +@@ -0,0 +1,246 @@ ++/* ++ * cdc2.c -- CDC Composite driver, with ECM and ACM support ++ * ++ * Copyright (C) 2008 David Brownell ++ * Copyright (C) 2008 Nokia Corporation ++ * ++ * 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 ++ */ ++ ++#include ++#include ++ ++#include "u_ether.h" ++#include "u_serial.h" ++ ++ ++#define DRIVER_DESC "CDC Composite Gadget" ++#define DRIVER_VERSION "King Kamehameha Day 2008" ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! ++ * Instead: allocate your own, using normal USB-IF procedures. ++ */ ++ ++/* Thanks to NetChip Technologies for donating this product ID. ++ * It's for devices with only this composite CDC configuration. ++ */ ++#define CDC_VENDOR_NUM 0x0525 /* NetChip */ ++#define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct usb_device_descriptor device_desc = { ++ .bLength = sizeof device_desc, ++ .bDescriptorType = USB_DT_DEVICE, ++ ++ .bcdUSB = __constant_cpu_to_le16(0x0200), ++ ++ .bDeviceClass = USB_CLASS_COMM, ++ .bDeviceSubClass = 0, ++ .bDeviceProtocol = 0, ++ /* .bMaxPacketSize0 = f(hardware) */ ++ ++ /* Vendor and product id can be overridden by module parameters. */ ++ .idVendor = __constant_cpu_to_le16(CDC_VENDOR_NUM), ++ .idProduct = __constant_cpu_to_le16(CDC_PRODUCT_NUM), ++ /* .bcdDevice = f(hardware) */ ++ /* .iManufacturer = DYNAMIC */ ++ /* .iProduct = DYNAMIC */ ++ /* NO SERIAL NUMBER */ ++ .bNumConfigurations = 1, ++}; ++ ++static struct usb_otg_descriptor otg_descriptor = { ++ .bLength = sizeof otg_descriptor, ++ .bDescriptorType = USB_DT_OTG, ++ ++ /* REVISIT SRP-only hardware is possible, although ++ * it would not be called "OTG" ... ++ */ ++ .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, ++}; ++ ++static const struct usb_descriptor_header *otg_desc[] = { ++ (struct usb_descriptor_header *) &otg_descriptor, ++ NULL, ++}; ++ ++ ++/* string IDs are assigned dynamically */ ++ ++#define STRING_MANUFACTURER_IDX 0 ++#define STRING_PRODUCT_IDX 1 ++ ++static char manufacturer[50]; ++ ++static struct usb_string strings_dev[] = { ++ [STRING_MANUFACTURER_IDX].s = manufacturer, ++ [STRING_PRODUCT_IDX].s = DRIVER_DESC, ++ { } /* end of list */ ++}; ++ ++static struct usb_gadget_strings stringtab_dev = { ++ .language = 0x0409, /* en-us */ ++ .strings = strings_dev, ++}; ++ ++static struct usb_gadget_strings *dev_strings[] = { ++ &stringtab_dev, ++ NULL, ++}; ++ ++static u8 hostaddr[ETH_ALEN]; ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * We _always_ have both CDC ECM and CDC ACM functions. ++ */ ++static int __init cdc_do_config(struct usb_configuration *c) ++{ ++ int status; ++ ++ if (gadget_is_otg(c->cdev->gadget)) { ++ c->descriptors = otg_desc; ++ c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; ++ } ++ ++ status = ecm_bind_config(c, hostaddr); ++ if (status < 0) ++ return status; ++ ++ status = acm_bind_config(c, 0); ++ if (status < 0) ++ return status; ++ ++ return 0; ++} ++ ++static struct usb_configuration cdc_config_driver = { ++ .label = "CDC Composite (ECM + ACM)", ++ .bind = cdc_do_config, ++ .bConfigurationValue = 1, ++ /* .iConfiguration = DYNAMIC */ ++ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, ++ .bMaxPower = 1, /* 2 mA, minimal */ ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int __init cdc_bind(struct usb_composite_dev *cdev) ++{ ++ int gcnum; ++ struct usb_gadget *gadget = cdev->gadget; ++ int status; ++ ++ if (!can_support_ecm(cdev->gadget)) { ++ ERROR(cdev, "controller '%s' not usable\n", gadget->name); ++ return -EINVAL; ++ } ++ ++ /* set up network link layer */ ++ status = gether_setup(cdev->gadget, hostaddr); ++ if (status < 0) ++ return status; ++ ++ /* set up serial link layer */ ++ status = gserial_setup(cdev->gadget, 1); ++ if (status < 0) ++ goto fail0; ++ ++ gcnum = usb_gadget_controller_number(gadget); ++ if (gcnum >= 0) ++ device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); ++ else { ++ /* We assume that can_support_ecm() tells the truth; ++ * but if the controller isn't recognized at all then ++ * that assumption is a bit more likely to be wrong. ++ */ ++ WARNING(cdev, "controller '%s' not recognized; trying %s\n", ++ gadget->name, ++ cdc_config_driver.label); ++ device_desc.bcdDevice = ++ __constant_cpu_to_le16(0x0300 | 0x0099); ++ } ++ ++ ++ /* Allocate string descriptor numbers ... note that string ++ * contents can be overridden by the composite_dev glue. ++ */ ++ ++ /* device descriptor strings: manufacturer, product */ ++ snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", ++ init_utsname()->sysname, init_utsname()->release, ++ gadget->name); ++ status = usb_string_id(cdev); ++ if (status < 0) ++ goto fail1; ++ strings_dev[STRING_MANUFACTURER_IDX].id = status; ++ device_desc.iManufacturer = status; ++ ++ status = usb_string_id(cdev); ++ if (status < 0) ++ goto fail1; ++ strings_dev[STRING_PRODUCT_IDX].id = status; ++ device_desc.iProduct = status; ++ ++ /* register our configuration */ ++ status = usb_add_config(cdev, &cdc_config_driver); ++ if (status < 0) ++ goto fail1; ++ ++ INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); ++ ++ return 0; ++ ++fail1: ++ gserial_cleanup(); ++fail0: ++ gether_cleanup(); ++ return status; ++} ++ ++static int __exit cdc_unbind(struct usb_composite_dev *cdev) ++{ ++ gserial_cleanup(); ++ gether_cleanup(); ++ return 0; ++} ++ ++static struct usb_composite_driver cdc_driver = { ++ .name = "g_cdc", ++ .dev = &device_desc, ++ .strings = dev_strings, ++ .bind = cdc_bind, ++ .unbind = __exit_p(cdc_unbind), ++}; ++ ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_AUTHOR("David Brownell"); ++MODULE_LICENSE("GPL"); ++ ++static int __init init(void) ++{ ++ return usb_composite_register(&cdc_driver); ++} ++module_init(init); ++ ++static void __exit cleanup(void) ++{ ++ usb_composite_unregister(&cdc_driver); ++} ++module_exit(cleanup); +diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c +new file mode 100644 +index 0000000..85c876c +--- /dev/null ++++ b/drivers/usb/gadget/composite.c +@@ -0,0 +1,1041 @@ ++/* ++ * composite.c - infrastructure for Composite USB Gadgets ++ * ++ * Copyright (C) 2006-2008 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 ++ */ ++ ++/* #define VERBOSE_DEBUG */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++/* ++ * The code in this file is utility code, used to build a gadget driver ++ * from one or more "function" drivers, one or more "configuration" ++ * objects, and a "usb_composite_driver" by gluing them together along ++ * with the relevant device-wide data. ++ */ ++ ++/* big enough to hold our biggest descriptor */ ++#define USB_BUFSIZ 512 ++ ++static struct usb_composite_driver *composite; ++ ++/* Some systems will need runtime overrides for the product identifers ++ * published in the device descriptor, either numbers or strings or both. ++ * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). ++ */ ++ ++static ushort idVendor; ++module_param(idVendor, ushort, 0); ++MODULE_PARM_DESC(idVendor, "USB Vendor ID"); ++ ++static ushort idProduct; ++module_param(idProduct, ushort, 0); ++MODULE_PARM_DESC(idProduct, "USB Product ID"); ++ ++static ushort bcdDevice; ++module_param(bcdDevice, ushort, 0); ++MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); ++ ++static char *iManufacturer; ++module_param(iManufacturer, charp, 0); ++MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); ++ ++static char *iProduct; ++module_param(iProduct, charp, 0); ++MODULE_PARM_DESC(iProduct, "USB Product string"); ++ ++static char *iSerialNumber; ++module_param(iSerialNumber, charp, 0); ++MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); ++ ++/*-------------------------------------------------------------------------*/ ++ ++/** ++ * usb_add_function() - add a function to a configuration ++ * @config: the configuration ++ * @function: the function being added ++ * Context: single threaded during gadget setup ++ * ++ * After initialization, each configuration must have one or more ++ * functions added to it. Adding a function involves calling its @bind() ++ * method to allocate resources such as interface and string identifiers ++ * and endpoints. ++ * ++ * This function returns the value of the function's bind(), which is ++ * zero for success else a negative errno value. ++ */ ++int __init usb_add_function(struct usb_configuration *config, ++ struct usb_function *function) ++{ ++ int value = -EINVAL; ++ ++ DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n", ++ function->name, function, ++ config->label, config); ++ ++ if (!function->set_alt || !function->disable) ++ goto done; ++ ++ function->config = config; ++ list_add_tail(&function->list, &config->functions); ++ ++ /* REVISIT *require* function->bind? */ ++ if (function->bind) { ++ value = function->bind(config, function); ++ if (value < 0) { ++ list_del(&function->list); ++ function->config = NULL; ++ } ++ } else ++ value = 0; ++ ++ /* We allow configurations that don't work at both speeds. ++ * If we run into a lowspeed Linux system, treat it the same ++ * as full speed ... it's the function drivers that will need ++ * to avoid bulk and ISO transfers. ++ */ ++ if (!config->fullspeed && function->descriptors) ++ config->fullspeed = true; ++ if (!config->highspeed && function->hs_descriptors) ++ config->highspeed = true; ++ ++done: ++ if (value) ++ DBG(config->cdev, "adding '%s'/%p --> %d\n", ++ function->name, function, value); ++ return value; ++} ++ ++/** ++ * usb_interface_id() - allocate an unused interface ID ++ * @config: configuration associated with the interface ++ * @function: function handling the interface ++ * Context: single threaded during gadget setup ++ * ++ * usb_interface_id() is called from usb_function.bind() callbacks to ++ * allocate new interface IDs. The function driver will then store that ++ * ID in interface, association, CDC union, and other descriptors. It ++ * will also handle any control requests targetted at that interface, ++ * particularly changing its altsetting via set_alt(). There may ++ * also be class-specific or vendor-specific requests to handle. ++ * ++ * All interface identifier should be allocated using this routine, to ++ * ensure that for example different functions don't wrongly assign ++ * different meanings to the same identifier. Note that since interface ++ * identifers are configuration-specific, functions used in more than ++ * one configuration (or more than once in a given configuration) need ++ * multiple versions of the relevant descriptors. ++ * ++ * Returns the interface ID which was allocated; or -ENODEV if no ++ * more interface IDs can be allocated. ++ */ ++int __init usb_interface_id(struct usb_configuration *config, ++ struct usb_function *function) ++{ ++ unsigned id = config->next_interface_id; ++ ++ if (id < MAX_CONFIG_INTERFACES) { ++ config->interface[id] = function; ++ config->next_interface_id = id + 1; ++ return id; ++ } ++ return -ENODEV; ++} ++ ++static int config_buf(struct usb_configuration *config, ++ enum usb_device_speed speed, void *buf, u8 type) ++{ ++ struct usb_config_descriptor *c = buf; ++ void *next = buf + USB_DT_CONFIG_SIZE; ++ int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE; ++ struct usb_function *f; ++ int status; ++ ++ /* write the config descriptor */ ++ c = buf; ++ c->bLength = USB_DT_CONFIG_SIZE; ++ c->bDescriptorType = type; ++ /* wTotalLength is written later */ ++ c->bNumInterfaces = config->next_interface_id; ++ c->bConfigurationValue = config->bConfigurationValue; ++ c->iConfiguration = config->iConfiguration; ++ c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; ++ c->bMaxPower = config->bMaxPower; ++ ++ /* There may be e.g. OTG descriptors */ ++ if (config->descriptors) { ++ status = usb_descriptor_fillbuf(next, len, ++ config->descriptors); ++ if (status < 0) ++ return status; ++ len -= status; ++ next += status; ++ } ++ ++ /* add each function's descriptors */ ++ list_for_each_entry(f, &config->functions, list) { ++ struct usb_descriptor_header **descriptors; ++ ++ if (speed == USB_SPEED_HIGH) ++ descriptors = f->hs_descriptors; ++ else ++ descriptors = f->descriptors; ++ if (!descriptors) ++ continue; ++ status = usb_descriptor_fillbuf(next, len, ++ (const struct usb_descriptor_header **) descriptors); ++ if (status < 0) ++ return status; ++ len -= status; ++ next += status; ++ } ++ ++ len = next - buf; ++ c->wTotalLength = cpu_to_le16(len); ++ return len; ++} ++ ++static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) ++{ ++ struct usb_gadget *gadget = cdev->gadget; ++ struct usb_configuration *c; ++ u8 type = w_value >> 8; ++ enum usb_device_speed speed = USB_SPEED_UNKNOWN; ++ ++ if (gadget_is_dualspeed(gadget)) { ++ int hs = 0; ++ ++ if (gadget->speed == USB_SPEED_HIGH) ++ hs = 1; ++ if (type == USB_DT_OTHER_SPEED_CONFIG) ++ hs = !hs; ++ if (hs) ++ speed = USB_SPEED_HIGH; ++ ++ } ++ ++ /* This is a lookup by config *INDEX* */ ++ w_value &= 0xff; ++ list_for_each_entry(c, &cdev->configs, list) { ++ /* ignore configs that won't work at this speed */ ++ if (speed == USB_SPEED_HIGH) { ++ if (!c->highspeed) ++ continue; ++ } else { ++ if (!c->fullspeed) ++ continue; ++ } ++ if (w_value == 0) ++ return config_buf(c, speed, cdev->req->buf, type); ++ w_value--; ++ } ++ return -EINVAL; ++} ++ ++static int count_configs(struct usb_composite_dev *cdev, unsigned type) ++{ ++ struct usb_gadget *gadget = cdev->gadget; ++ struct usb_configuration *c; ++ unsigned count = 0; ++ int hs = 0; ++ ++ if (gadget_is_dualspeed(gadget)) { ++ if (gadget->speed == USB_SPEED_HIGH) ++ hs = 1; ++ if (type == USB_DT_DEVICE_QUALIFIER) ++ hs = !hs; ++ } ++ list_for_each_entry(c, &cdev->configs, list) { ++ /* ignore configs that won't work at this speed */ ++ if (hs) { ++ if (!c->highspeed) ++ continue; ++ } else { ++ if (!c->fullspeed) ++ continue; ++ } ++ count++; ++ } ++ return count; ++} ++ ++static void device_qual(struct usb_composite_dev *cdev) ++{ ++ struct usb_qualifier_descriptor *qual = cdev->req->buf; ++ ++ qual->bLength = sizeof(*qual); ++ qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER; ++ /* POLICY: same bcdUSB and device type info at both speeds */ ++ qual->bcdUSB = cdev->desc.bcdUSB; ++ qual->bDeviceClass = cdev->desc.bDeviceClass; ++ qual->bDeviceSubClass = cdev->desc.bDeviceSubClass; ++ qual->bDeviceProtocol = cdev->desc.bDeviceProtocol; ++ /* ASSUME same EP0 fifo size at both speeds */ ++ qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0; ++ qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER); ++ qual->bRESERVED = 0; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void reset_config(struct usb_composite_dev *cdev) ++{ ++ struct usb_function *f; ++ ++ DBG(cdev, "reset config\n"); ++ ++ list_for_each_entry(f, &cdev->config->functions, list) { ++ if (f->disable) ++ f->disable(f); ++ } ++ cdev->config = NULL; ++} ++ ++static int set_config(struct usb_composite_dev *cdev, ++ const struct usb_ctrlrequest *ctrl, unsigned number) ++{ ++ struct usb_gadget *gadget = cdev->gadget; ++ struct usb_configuration *c = NULL; ++ int result = -EINVAL; ++ unsigned power = gadget_is_otg(gadget) ? 8 : 100; ++ int tmp; ++ ++ if (cdev->config) ++ reset_config(cdev); ++ ++ if (number) { ++ list_for_each_entry(c, &cdev->configs, list) { ++ if (c->bConfigurationValue == number) { ++ result = 0; ++ break; ++ } ++ } ++ if (result < 0) ++ goto done; ++ } else ++ result = 0; ++ ++ INFO(cdev, "%s speed config #%d: %s\n", ++ ({ char *speed; ++ switch (gadget->speed) { ++ case USB_SPEED_LOW: speed = "low"; break; ++ case USB_SPEED_FULL: speed = "full"; break; ++ case USB_SPEED_HIGH: speed = "high"; break; ++ default: speed = "?"; break; ++ } ; speed; }), number, c ? c->label : "unconfigured"); ++ ++ if (!c) ++ goto done; ++ ++ cdev->config = c; ++ ++ /* Initialize all interfaces by setting them to altsetting zero. */ ++ for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { ++ struct usb_function *f = c->interface[tmp]; ++ ++ if (!f) ++ break; ++ ++ result = f->set_alt(f, tmp, 0); ++ if (result < 0) { ++ DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n", ++ tmp, f->name, f, result); ++ ++ reset_config(cdev); ++ goto done; ++ } ++ } ++ ++ /* when we return, be sure our power usage is valid */ ++ power = 2 * c->bMaxPower; ++done: ++ usb_gadget_vbus_draw(gadget, power); ++ return result; ++} ++ ++/** ++ * usb_add_config() - add a configuration to a device. ++ * @cdev: wraps the USB gadget ++ * @config: the configuration, with bConfigurationValue assigned ++ * Context: single threaded during gadget setup ++ * ++ * One of the main tasks of a composite driver's bind() routine is to ++ * add each of the configurations it supports, using this routine. ++ * ++ * This function returns the value of the configuration's bind(), which ++ * is zero for success else a negative errno value. Binding configurations ++ * assigns global resources including string IDs, and per-configuration ++ * resources such as interface IDs and endpoints. ++ */ ++int __init usb_add_config(struct usb_composite_dev *cdev, ++ struct usb_configuration *config) ++{ ++ int status = -EINVAL; ++ struct usb_configuration *c; ++ ++ DBG(cdev, "adding config #%u '%s'/%p\n", ++ config->bConfigurationValue, ++ config->label, config); ++ ++ if (!config->bConfigurationValue || !config->bind) ++ goto done; ++ ++ /* Prevent duplicate configuration identifiers */ ++ list_for_each_entry(c, &cdev->configs, list) { ++ if (c->bConfigurationValue == config->bConfigurationValue) { ++ status = -EBUSY; ++ goto done; ++ } ++ } ++ ++ config->cdev = cdev; ++ list_add_tail(&config->list, &cdev->configs); ++ ++ INIT_LIST_HEAD(&config->functions); ++ config->next_interface_id = 0; ++ ++ status = config->bind(config); ++ if (status < 0) { ++ list_del(&config->list); ++ config->cdev = NULL; ++ } else { ++ unsigned i; ++ ++ DBG(cdev, "cfg %d/%p speeds:%s%s\n", ++ config->bConfigurationValue, config, ++ config->highspeed ? " high" : "", ++ config->fullspeed ++ ? (gadget_is_dualspeed(cdev->gadget) ++ ? " full" ++ : " full/low") ++ : ""); ++ ++ for (i = 0; i < MAX_CONFIG_INTERFACES; i++) { ++ struct usb_function *f = config->interface[i]; ++ ++ if (!f) ++ continue; ++ DBG(cdev, " interface %d = %s/%p\n", ++ i, f->name, f); ++ } ++ } ++ ++ /* set_alt(), or next config->bind(), sets up ++ * ep->driver_data as needed. ++ */ ++ usb_ep_autoconfig_reset(cdev->gadget); ++ ++done: ++ if (status) ++ DBG(cdev, "added config '%s'/%u --> %d\n", config->label, ++ config->bConfigurationValue, status); ++ return status; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* We support strings in multiple languages ... string descriptor zero ++ * says which languages are supported. The typical case will be that ++ * only one language (probably English) is used, with I18N handled on ++ * the host side. ++ */ ++ ++static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf) ++{ ++ const struct usb_gadget_strings *s; ++ u16 language; ++ __le16 *tmp; ++ ++ while (*sp) { ++ s = *sp; ++ language = cpu_to_le16(s->language); ++ for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) { ++ if (*tmp == language) ++ goto repeat; ++ } ++ *tmp++ = language; ++repeat: ++ sp++; ++ } ++} ++ ++static int lookup_string( ++ struct usb_gadget_strings **sp, ++ void *buf, ++ u16 language, ++ int id ++) ++{ ++ struct usb_gadget_strings *s; ++ int value; ++ ++ while (*sp) { ++ s = *sp++; ++ if (s->language != language) ++ continue; ++ value = usb_gadget_get_string(s, id, buf); ++ if (value > 0) ++ return value; ++ } ++ return -EINVAL; ++} ++ ++static int get_string(struct usb_composite_dev *cdev, ++ void *buf, u16 language, int id) ++{ ++ struct usb_configuration *c; ++ struct usb_function *f; ++ int len; ++ ++ /* Yes, not only is USB's I18N support probably more than most ++ * folk will ever care about ... also, it's all supported here. ++ * (Except for UTF8 support for Unicode's "Astral Planes".) ++ */ ++ ++ /* 0 == report all available language codes */ ++ if (id == 0) { ++ struct usb_string_descriptor *s = buf; ++ struct usb_gadget_strings **sp; ++ ++ memset(s, 0, 256); ++ s->bDescriptorType = USB_DT_STRING; ++ ++ sp = composite->strings; ++ if (sp) ++ collect_langs(sp, s->wData); ++ ++ list_for_each_entry(c, &cdev->configs, list) { ++ sp = c->strings; ++ if (sp) ++ collect_langs(sp, s->wData); ++ ++ list_for_each_entry(f, &c->functions, list) { ++ sp = f->strings; ++ if (sp) ++ collect_langs(sp, s->wData); ++ } ++ } ++ ++ for (len = 0; s->wData[len] && len <= 126; len++) ++ continue; ++ if (!len) ++ return -EINVAL; ++ ++ s->bLength = 2 * (len + 1); ++ return s->bLength; ++ } ++ ++ /* Otherwise, look up and return a specified string. String IDs ++ * are device-scoped, so we look up each string table we're told ++ * about. These lookups are infrequent; simpler-is-better here. ++ */ ++ if (composite->strings) { ++ len = lookup_string(composite->strings, buf, language, id); ++ if (len > 0) ++ return len; ++ } ++ list_for_each_entry(c, &cdev->configs, list) { ++ if (c->strings) { ++ len = lookup_string(c->strings, buf, language, id); ++ if (len > 0) ++ return len; ++ } ++ list_for_each_entry(f, &c->functions, list) { ++ if (!f->strings) ++ continue; ++ len = lookup_string(f->strings, buf, language, id); ++ if (len > 0) ++ return len; ++ } ++ } ++ return -EINVAL; ++} ++ ++/** ++ * usb_string_id() - allocate an unused string ID ++ * @cdev: the device whose string descriptor IDs are being allocated ++ * Context: single threaded during gadget setup ++ * ++ * @usb_string_id() is called from bind() callbacks to allocate ++ * string IDs. Drivers for functions, configurations, or gadgets will ++ * then store that ID in the appropriate descriptors and string table. ++ * ++ * All string identifier should be allocated using this routine, to ++ * ensure that for example different functions don't wrongly assign ++ * different meanings to the same identifier. ++ */ ++int __init usb_string_id(struct usb_composite_dev *cdev) ++{ ++ if (cdev->next_string_id < 254) { ++ /* string id 0 is reserved */ ++ cdev->next_string_id++; ++ return cdev->next_string_id; ++ } ++ return -ENODEV; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ if (req->status || req->actual != req->length) ++ DBG((struct usb_composite_dev *) ep->driver_data, ++ "setup complete --> %d, %d/%d\n", ++ req->status, req->actual, req->length); ++} ++ ++/* ++ * The setup() callback implements all the ep0 functionality that's ++ * not handled lower down, in hardware or the hardware driver(like ++ * device and endpoint feature flags, and their status). It's all ++ * housekeeping for the gadget function we're implementing. Most of ++ * the work is in config and function specific setup. ++ */ ++static int ++composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ++{ ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ struct usb_request *req = cdev->req; ++ int value = -EOPNOTSUPP; ++ u16 w_index = le16_to_cpu(ctrl->wIndex); ++ u16 w_value = le16_to_cpu(ctrl->wValue); ++ u16 w_length = le16_to_cpu(ctrl->wLength); ++ struct usb_function *f = NULL; ++ ++ /* partial re-init of the response message; the function or the ++ * gadget might need to intercept e.g. a control-OUT completion ++ * when we delegate to it. ++ */ ++ req->zero = 0; ++ req->complete = composite_setup_complete; ++ req->length = USB_BUFSIZ; ++ gadget->ep0->driver_data = cdev; ++ ++ switch (ctrl->bRequest) { ++ ++ /* we handle all standard USB descriptors */ ++ case USB_REQ_GET_DESCRIPTOR: ++ if (ctrl->bRequestType != USB_DIR_IN) ++ goto unknown; ++ switch (w_value >> 8) { ++ ++ case USB_DT_DEVICE: ++ cdev->desc.bNumConfigurations = ++ count_configs(cdev, USB_DT_DEVICE); ++ value = min(w_length, (u16) sizeof cdev->desc); ++ memcpy(req->buf, &cdev->desc, value); ++ break; ++ case USB_DT_DEVICE_QUALIFIER: ++ if (!gadget_is_dualspeed(gadget)) ++ break; ++ device_qual(cdev); ++ value = min_t(int, w_length, ++ sizeof(struct usb_qualifier_descriptor)); ++ break; ++ case USB_DT_OTHER_SPEED_CONFIG: ++ if (!gadget_is_dualspeed(gadget)) ++ break; ++ /* FALLTHROUGH */ ++ case USB_DT_CONFIG: ++ value = config_desc(cdev, w_value); ++ if (value >= 0) ++ value = min(w_length, (u16) value); ++ break; ++ case USB_DT_STRING: ++ value = get_string(cdev, req->buf, ++ w_index, w_value & 0xff); ++ if (value >= 0) ++ value = min(w_length, (u16) value); ++ break; ++ } ++ break; ++ ++ /* any number of configs can work */ ++ case USB_REQ_SET_CONFIGURATION: ++ if (ctrl->bRequestType != 0) ++ goto unknown; ++ if (gadget_is_otg(gadget)) { ++ if (gadget->a_hnp_support) ++ DBG(cdev, "HNP available\n"); ++ else if (gadget->a_alt_hnp_support) ++ DBG(cdev, "HNP on another port\n"); ++ else ++ VDBG(cdev, "HNP inactive\n"); ++ } ++ spin_lock(&cdev->lock); ++ value = set_config(cdev, ctrl, w_value); ++ spin_unlock(&cdev->lock); ++ break; ++ case USB_REQ_GET_CONFIGURATION: ++ if (ctrl->bRequestType != USB_DIR_IN) ++ goto unknown; ++ if (cdev->config) ++ *(u8 *)req->buf = cdev->config->bConfigurationValue; ++ else ++ *(u8 *)req->buf = 0; ++ value = min(w_length, (u16) 1); ++ break; ++ ++ /* function drivers must handle get/set altsetting; if there's ++ * no get() method, we know only altsetting zero works. ++ */ ++ case USB_REQ_SET_INTERFACE: ++ if (ctrl->bRequestType != USB_RECIP_INTERFACE) ++ goto unknown; ++ if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) ++ break; ++ f = cdev->config->interface[w_index]; ++ if (!f) ++ break; ++ if (w_value && !f->get_alt) ++ break; ++ value = f->set_alt(f, w_index, w_value); ++ break; ++ case USB_REQ_GET_INTERFACE: ++ if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) ++ goto unknown; ++ if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) ++ break; ++ f = cdev->config->interface[w_index]; ++ if (!f) ++ break; ++ /* lots of interfaces only need altsetting zero... */ ++ value = f->get_alt ? f->get_alt(f, w_index) : 0; ++ if (value < 0) ++ break; ++ *((u8 *)req->buf) = value; ++ value = min(w_length, (u16) 1); ++ break; ++ default: ++unknown: ++ VDBG(cdev, ++ "non-core control req%02x.%02x v%04x i%04x l%d\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ w_value, w_index, w_length); ++ ++ /* functions always handle their interfaces ... punt other ++ * recipients (endpoint, other, WUSB, ...) to the current ++ * configuration code. ++ * ++ * REVISIT it could make sense to let the composite device ++ * take such requests too, if that's ever needed: to work ++ * in config 0, etc. ++ */ ++ if ((ctrl->bRequestType & USB_RECIP_MASK) ++ == USB_RECIP_INTERFACE) { ++ f = cdev->config->interface[w_index]; ++ if (f && f->setup) ++ value = f->setup(f, ctrl); ++ else ++ f = NULL; ++ } ++ if (value < 0 && !f) { ++ struct usb_configuration *c; ++ ++ c = cdev->config; ++ if (c && c->setup) ++ value = c->setup(c, ctrl); ++ } ++ ++ goto done; ++ } ++ ++ /* respond with data transfer before status phase? */ ++ if (value >= 0) { ++ req->length = value; ++ req->zero = value < w_length; ++ value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); ++ if (value < 0) { ++ DBG(cdev, "ep_queue --> %d\n", value); ++ req->status = 0; ++ composite_setup_complete(gadget->ep0, req); ++ } ++ } ++ ++done: ++ /* device either stalls (value < 0) or reports success */ ++ return value; ++} ++ ++static void composite_disconnect(struct usb_gadget *gadget) ++{ ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ unsigned long flags; ++ ++ /* REVISIT: should we have config and device level ++ * disconnect callbacks? ++ */ ++ spin_lock_irqsave(&cdev->lock, flags); ++ if (cdev->config) ++ reset_config(cdev); ++ spin_unlock_irqrestore(&cdev->lock, flags); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void /* __init_or_exit */ ++composite_unbind(struct usb_gadget *gadget) ++{ ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ ++ /* composite_disconnect() must already have been called ++ * by the underlying peripheral controller driver! ++ * so there's no i/o concurrency that could affect the ++ * state protected by cdev->lock. ++ */ ++ WARN_ON(cdev->config); ++ ++ while (!list_empty(&cdev->configs)) { ++ struct usb_configuration *c; ++ ++ c = list_first_entry(&cdev->configs, ++ struct usb_configuration, list); ++ while (!list_empty(&c->functions)) { ++ struct usb_function *f; ++ ++ f = list_first_entry(&c->functions, ++ struct usb_function, list); ++ list_del(&f->list); ++ if (f->unbind) { ++ DBG(cdev, "unbind function '%s'/%p\n", ++ f->name, f); ++ f->unbind(c, f); ++ /* may free memory for "f" */ ++ } ++ } ++ list_del(&c->list); ++ if (c->unbind) { ++ DBG(cdev, "unbind config '%s'/%p\n", c->label, c); ++ c->unbind(c); ++ /* may free memory for "c" */ ++ } ++ } ++ if (composite->unbind) ++ composite->unbind(cdev); ++ ++ if (cdev->req) { ++ kfree(cdev->req->buf); ++ usb_ep_free_request(gadget->ep0, cdev->req); ++ } ++ kfree(cdev); ++ set_gadget_data(gadget, NULL); ++ composite = NULL; ++} ++ ++static void __init ++string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s) ++{ ++ struct usb_string *str = tab->strings; ++ ++ for (str = tab->strings; str->s; str++) { ++ if (str->id == id) { ++ str->s = s; ++ return; ++ } ++ } ++} ++ ++static void __init ++string_override(struct usb_gadget_strings **tab, u8 id, const char *s) ++{ ++ while (*tab) { ++ string_override_one(*tab, id, s); ++ tab++; ++ } ++} ++ ++static int __init composite_bind(struct usb_gadget *gadget) ++{ ++ struct usb_composite_dev *cdev; ++ int status = -ENOMEM; ++ ++ cdev = kzalloc(sizeof *cdev, GFP_KERNEL); ++ if (!cdev) ++ return status; ++ ++ spin_lock_init(&cdev->lock); ++ cdev->gadget = gadget; ++ set_gadget_data(gadget, cdev); ++ INIT_LIST_HEAD(&cdev->configs); ++ ++ /* preallocate control response and buffer */ ++ cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); ++ if (!cdev->req) ++ goto fail; ++ cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); ++ if (!cdev->req->buf) ++ goto fail; ++ cdev->req->complete = composite_setup_complete; ++ gadget->ep0->driver_data = cdev; ++ ++ cdev->bufsiz = USB_BUFSIZ; ++ cdev->driver = composite; ++ ++ usb_gadget_set_selfpowered(gadget); ++ ++ /* interface and string IDs start at zero via kzalloc. ++ * we force endpoints to start unassigned; few controller ++ * drivers will zero ep->driver_data. ++ */ ++ usb_ep_autoconfig_reset(cdev->gadget); ++ ++ /* composite gadget needs to assign strings for whole device (like ++ * serial number), register function drivers, potentially update ++ * power state and consumption, etc ++ */ ++ status = composite->bind(cdev); ++ if (status < 0) ++ goto fail; ++ ++ cdev->desc = *composite->dev; ++ cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; ++ ++ /* standardized runtime overrides for device ID data */ ++ if (idVendor) ++ cdev->desc.idVendor = cpu_to_le16(idVendor); ++ if (idProduct) ++ cdev->desc.idProduct = cpu_to_le16(idProduct); ++ if (bcdDevice) ++ cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); ++ ++ /* strings can't be assigned before bind() allocates the ++ * releavnt identifiers ++ */ ++ if (cdev->desc.iManufacturer && iManufacturer) ++ string_override(composite->strings, ++ cdev->desc.iManufacturer, iManufacturer); ++ if (cdev->desc.iProduct && iProduct) ++ string_override(composite->strings, ++ cdev->desc.iProduct, iProduct); ++ if (cdev->desc.iSerialNumber && iSerialNumber) ++ string_override(composite->strings, ++ cdev->desc.iSerialNumber, iSerialNumber); ++ ++ INFO(cdev, "%s ready\n", composite->name); ++ return 0; ++ ++fail: ++ composite_unbind(gadget); ++ return status; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void ++composite_suspend(struct usb_gadget *gadget) ++{ ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ struct usb_function *f; ++ ++ /* REVISIT: should we have config and device level ++ * suspend/resume callbacks? ++ */ ++ DBG(cdev, "suspend\n"); ++ if (cdev->config) { ++ list_for_each_entry(f, &cdev->config->functions, list) { ++ if (f->suspend) ++ f->suspend(f); ++ } ++ } ++} ++ ++static void ++composite_resume(struct usb_gadget *gadget) ++{ ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ struct usb_function *f; ++ ++ /* REVISIT: should we have config and device level ++ * suspend/resume callbacks? ++ */ ++ DBG(cdev, "resume\n"); ++ if (cdev->config) { ++ list_for_each_entry(f, &cdev->config->functions, list) { ++ if (f->resume) ++ f->resume(f); ++ } ++ } ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct usb_gadget_driver composite_driver = { ++ .speed = USB_SPEED_HIGH, ++ ++ .bind = composite_bind, ++ .unbind = __exit_p(composite_unbind), ++ ++ .setup = composite_setup, ++ .disconnect = composite_disconnect, ++ ++ .suspend = composite_suspend, ++ .resume = composite_resume, ++ ++ .driver = { ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++/** ++ * usb_composite_register() - register a composite driver ++ * @driver: the driver to register ++ * Context: single threaded during gadget setup ++ * ++ * This function is used to register drivers using the composite driver ++ * framework. The return value is zero, or a negative errno value. ++ * Those values normally come from the driver's @bind method, which does ++ * all the work of setting up the driver to match the hardware. ++ * ++ * On successful return, the gadget is ready to respond to requests from ++ * the host, unless one of its components invokes usb_gadget_disconnect() ++ * while it was binding. That would usually be done in order to wait for ++ * some userspace participation. ++ */ ++int __init usb_composite_register(struct usb_composite_driver *driver) ++{ ++ if (!driver || !driver->dev || !driver->bind || composite) ++ return -EINVAL; ++ ++ if (!driver->name) ++ driver->name = "composite"; ++ composite_driver.function = (char *) driver->name; ++ composite_driver.driver.name = driver->name; ++ composite = driver; ++ ++ return usb_gadget_register_driver(&composite_driver); ++} ++ ++/** ++ * usb_composite_unregister() - unregister a composite driver ++ * @driver: the driver to unregister ++ * ++ * This function is used to unregister drivers using the composite ++ * driver framework. ++ */ ++void __exit usb_composite_unregister(struct usb_composite_driver *driver) ++{ ++ if (composite != driver) ++ return; ++ usb_gadget_unregister_driver(&composite_driver); ++} +diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c +index a4e54b2..1ca1c32 100644 +--- a/drivers/usb/gadget/config.c ++++ b/drivers/usb/gadget/config.c +@@ -96,7 +96,7 @@ int usb_gadget_config_buf( + /* config descriptor first */ + if (length < USB_DT_CONFIG_SIZE || !desc) + return -EINVAL; +- *cp = *config; ++ *cp = *config; + + /* then interface/endpoint/class/vendor/... */ + len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, +@@ -115,3 +115,77 @@ int usb_gadget_config_buf( + return len; + } + ++/** ++ * usb_copy_descriptors - copy a vector of USB descriptors ++ * @src: null-terminated vector to copy ++ * Context: initialization code, which may sleep ++ * ++ * This makes a copy of a vector of USB descriptors. Its primary use ++ * is to support usb_function objects which can have multiple copies, ++ * each needing different descriptors. Functions may have static ++ * tables of descriptors, which are used as templates and customized ++ * with identifiers (for interfaces, strings, endpoints, and more) ++ * as needed by a given function instance. ++ */ ++struct usb_descriptor_header **__init ++usb_copy_descriptors(struct usb_descriptor_header **src) ++{ ++ struct usb_descriptor_header **tmp; ++ unsigned bytes; ++ unsigned n_desc; ++ void *mem; ++ struct usb_descriptor_header **ret; ++ ++ /* count descriptors and their sizes; then add vector size */ ++ for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) ++ bytes += (*tmp)->bLength; ++ bytes += (n_desc + 1) * sizeof(*tmp); ++ ++ mem = kmalloc(bytes, GFP_KERNEL); ++ if (!mem) ++ return NULL; ++ ++ /* fill in pointers starting at "tmp", ++ * to descriptors copied starting at "mem"; ++ * and return "ret" ++ */ ++ tmp = mem; ++ ret = mem; ++ mem += (n_desc + 1) * sizeof(*tmp); ++ while (*src) { ++ memcpy(mem, *src, (*src)->bLength); ++ *tmp = mem; ++ tmp++; ++ mem += (*src)->bLength; ++ src++; ++ } ++ *tmp = NULL; ++ ++ return ret; ++} ++ ++/** ++ * usb_find_endpoint - find a copy of an endpoint descriptor ++ * @src: original vector of descriptors ++ * @copy: copy of @src ++ * @ep: endpoint descriptor found in @src ++ * ++ * This returns the copy of the @match descriptor made for @copy. Its ++ * intended use is to help remembering the endpoint descriptor to use ++ * when enabling a given endpoint. ++ */ ++struct usb_endpoint_descriptor *__init ++usb_find_endpoint( ++ struct usb_descriptor_header **src, ++ struct usb_descriptor_header **copy, ++ struct usb_endpoint_descriptor *match ++) ++{ ++ while (*src) { ++ if (*src == (void *) match) ++ return (void *)*copy; ++ src++; ++ copy++; ++ } ++ return NULL; ++} +diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c +index 4203619..7600a0c 100644 +--- a/drivers/usb/gadget/dummy_hcd.c ++++ b/drivers/usb/gadget/dummy_hcd.c +@@ -542,13 +542,14 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req, + req->req.context = dum; + req->req.complete = fifo_complete; + ++ list_add_tail(&req->queue, &ep->queue); + spin_unlock (&dum->lock); + _req->actual = _req->length; + _req->status = 0; + _req->complete (_ep, _req); + spin_lock (&dum->lock); +- } +- list_add_tail (&req->queue, &ep->queue); ++ } else ++ list_add_tail(&req->queue, &ep->queue); + spin_unlock_irqrestore (&dum->lock, flags); + + /* real hardware would likely enable transfers here, in case +@@ -862,7 +863,7 @@ static int dummy_udc_probe (struct platform_device *pdev) + /* maybe claim OTG support, though we won't complete HNP */ + dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0); + +- strcpy (dum->gadget.dev.bus_id, "gadget"); ++ dev_set_name(&dum->gadget.dev, "gadget"); + dum->gadget.dev.parent = &pdev->dev; + dum->gadget.dev.release = dummy_gadget_release; + rc = device_register (&dum->gadget.dev); +@@ -1865,7 +1866,7 @@ static int dummy_hcd_probe(struct platform_device *pdev) + + dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); + +- hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id); ++ hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); + if (!hcd) + return -ENOMEM; + the_controller = hcd_to_dummy (hcd); +diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c +index 8bdad22..9462e30 100644 +--- a/drivers/usb/gadget/epautoconf.c ++++ b/drivers/usb/gadget/epautoconf.c +@@ -159,6 +159,7 @@ ep_matches ( + /* MATCH!! */ + + /* report address */ ++ desc->bEndpointAddress &= USB_DIR_IN; + if (isdigit (ep->name [2])) { + u8 num = simple_strtol (&ep->name [2], NULL, 10); + desc->bEndpointAddress |= num; +diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c +index 8d61ea6..bcac2e6 100644 +--- a/drivers/usb/gadget/ether.c ++++ b/drivers/usb/gadget/ether.c +@@ -1,8 +1,9 @@ + /* + * ether.c -- Ethernet gadget driver, with CDC and non-CDC options + * +- * Copyright (C) 2003-2005 David Brownell ++ * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger ++ * Copyright (C) 2008 Nokia Corporation + * + * 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 +@@ -23,18 +24,9 @@ + + #include + #include +-#include +-#include +-#include +-#include + +-#include +-#include +-#include ++#include "u_ether.h" + +-#include "gadget_chips.h" +- +-/*-------------------------------------------------------------------------*/ + + /* + * Ethernet gadget driver -- with CDC and non-CDC options +@@ -46,7 +38,11 @@ + * this USB-IF standard as its open-systems interoperability solution; + * most host side USB stacks (except from Microsoft) support it. + * +- * There's some hardware that can't talk CDC. We make that hardware ++ * This is sometimes called "CDC ECM" (Ethernet Control Model) to support ++ * TLA-soup. "CDC ACM" (Abstract Control Model) is for modems, and a new ++ * "CDC EEM" (Ethernet Emulation Model) is starting to spread. ++ * ++ * There's some hardware that can't talk CDC ECM. We make that hardware + * implement a "minimalist" vendor-agnostic CDC core: same framing, but + * link-level setup only requires activating the configuration. Only the + * endpoint descriptors, and product/vendor IDs, are relevant; no control +@@ -64,70 +60,40 @@ + * A third option is also in use. Rather than CDC Ethernet, or something + * simpler, Microsoft pushes their own approach: RNDIS. The published + * RNDIS specs are ambiguous and appear to be incomplete, and are also +- * needlessly complex. ++ * needlessly complex. They borrow more from CDC ACM than CDC ECM. + */ + + #define DRIVER_DESC "Ethernet Gadget" +-#define DRIVER_VERSION "May Day 2005" +- +-static const char shortname [] = "ether"; +-static const char driver_desc [] = DRIVER_DESC; +- +-#define RX_EXTRA 20 /* guard against rx overflows */ +- +-#include "rndis.h" ++#define DRIVER_VERSION "Memorial Day 2008" + +-#ifndef CONFIG_USB_ETH_RNDIS +-#define rndis_uninit(x) do{}while(0) +-#define rndis_deregister(c) do{}while(0) +-#define rndis_exit() do{}while(0) ++#ifdef CONFIG_USB_ETH_RNDIS ++#define PREFIX "RNDIS/" ++#else ++#define PREFIX "" + #endif + +-/* CDC and RNDIS support the same host-chosen outgoing packet filters. */ +-#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ +- |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ +- |USB_CDC_PACKET_TYPE_PROMISCUOUS \ +- |USB_CDC_PACKET_TYPE_DIRECTED) +- +- +-/*-------------------------------------------------------------------------*/ +- +-struct eth_dev { +- spinlock_t lock; +- struct usb_gadget *gadget; +- struct usb_request *req; /* for control responses */ +- struct usb_request *stat_req; /* for cdc & rndis status */ +- +- u8 config; +- struct usb_ep *in_ep, *out_ep, *status_ep; +- const struct usb_endpoint_descriptor +- *in, *out, *status; +- +- spinlock_t req_lock; +- struct list_head tx_reqs, rx_reqs; +- +- struct net_device *net; +- struct net_device_stats stats; +- atomic_t tx_qlen; +- +- struct work_struct work; +- unsigned zlp:1; +- unsigned cdc:1; +- unsigned rndis:1; +- unsigned suspended:1; +- u16 cdc_filter; +- unsigned long todo; +-#define WORK_RX_MEMORY 0 +- int rndis_config; +- u8 host_mac [ETH_ALEN]; +-}; +- +-/* This version autoconfigures as much as possible at run-time. ++/* ++ * This driver aims for interoperability by using CDC ECM unless ++ * ++ * can_support_ecm() ++ * ++ * returns false, in which case it supports the CDC Subset. By default, ++ * that returns true; most hardware has no problems with CDC ECM, that's ++ * a good default. Previous versions of this driver had no default; this ++ * version changes that, removing overhead for new controller support. + * +- * It also ASSUMES a self-powered device, without remote wakeup, +- * although remote wakeup support would make sense. ++ * IF YOUR HARDWARE CAN'T SUPPORT CDC ECM, UPDATE THAT ROUTINE! + */ + ++static inline bool has_rndis(void) ++{ ++#ifdef CONFIG_USB_ETH_RNDIS ++ return true; ++#else ++ return false; ++#endif ++} ++ + /*-------------------------------------------------------------------------*/ + + /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! +@@ -137,8 +103,8 @@ struct eth_dev { + /* Thanks to NetChip Technologies for donating this product ID. + * It's for devices with only CDC Ethernet configurations. + */ +-#define CDC_VENDOR_NUM 0x0525 /* NetChip */ +-#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ ++#define CDC_VENDOR_NUM 0x0525 /* NetChip */ ++#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ + + /* For hardware that can't talk CDC, we use the same vendor ID that + * ARM Linux has used for ethernet-over-usb, both with sa1100 and +@@ -162,274 +128,9 @@ struct eth_dev { + #define RNDIS_VENDOR_NUM 0x0525 /* NetChip */ + #define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */ + +- +-/* Some systems will want different product identifers published in the +- * device descriptor, either numbers or strings or both. These string +- * parameters are in UTF-8 (superset of ASCII's 7 bit characters). +- */ +- +-static ushort idVendor; +-module_param(idVendor, ushort, S_IRUGO); +-MODULE_PARM_DESC(idVendor, "USB Vendor ID"); +- +-static ushort idProduct; +-module_param(idProduct, ushort, S_IRUGO); +-MODULE_PARM_DESC(idProduct, "USB Product ID"); +- +-static ushort bcdDevice; +-module_param(bcdDevice, ushort, S_IRUGO); +-MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); +- +-static char *iManufacturer; +-module_param(iManufacturer, charp, S_IRUGO); +-MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); +- +-static char *iProduct; +-module_param(iProduct, charp, S_IRUGO); +-MODULE_PARM_DESC(iProduct, "USB Product string"); +- +-static char *iSerialNumber; +-module_param(iSerialNumber, charp, S_IRUGO); +-MODULE_PARM_DESC(iSerialNumber, "SerialNumber"); +- +-/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ +-static char *dev_addr; +-module_param(dev_addr, charp, S_IRUGO); +-MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); +- +-/* this address is invisible to ifconfig */ +-static char *host_addr; +-module_param(host_addr, charp, S_IRUGO); +-MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); +- +- +-/*-------------------------------------------------------------------------*/ +- +-/* Include CDC support if we could run on CDC-capable hardware. */ +- +-#ifdef CONFIG_USB_GADGET_NET2280 +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_DUMMY_HCD +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_GOKU +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_LH7A40X +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_MQ11XX +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_OMAP +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_N9604 +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_S3C2410 +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_AT91 +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_MUSBHSFC +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_MUSB_HDRC +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_ATMEL_USBA +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_FSL_USB2 +-#define DEV_CONFIG_CDC +-#endif +- +-/* For CDC-incapable hardware, choose the simple cdc subset. +- * Anything that talks bulk (without notable bugs) can do this. +- */ +-#ifdef CONFIG_USB_GADGET_PXA2XX +-#define DEV_CONFIG_SUBSET +-#endif +- +-#ifdef CONFIG_USB_GADGET_PXA27X +-#define DEV_CONFIG_SUBSET +-#endif +- +-#ifdef CONFIG_USB_GADGET_SUPERH +-#define DEV_CONFIG_SUBSET +-#endif +- +-#ifdef CONFIG_USB_GADGET_SA1100 +-/* use non-CDC for backwards compatibility */ +-#define DEV_CONFIG_SUBSET +-#endif +- +-#ifdef CONFIG_USB_GADGET_M66592 +-#define DEV_CONFIG_CDC +-#endif +- +-#ifdef CONFIG_USB_GADGET_AMD5536UDC +-#define DEV_CONFIG_CDC +-#endif +- +- +-/*-------------------------------------------------------------------------*/ +- +-/* "main" config is either CDC, or its simple subset */ +-static inline int is_cdc(struct eth_dev *dev) +-{ +-#if !defined(DEV_CONFIG_SUBSET) +- return 1; /* only cdc possible */ +-#elif !defined (DEV_CONFIG_CDC) +- return 0; /* only subset possible */ +-#else +- return dev->cdc; /* depends on what hardware we found */ +-#endif +-} +- +-/* "secondary" RNDIS config may sometimes be activated */ +-static inline int rndis_activ