usb: gadget: patches for v3.8

renesas_usbhs implements ->pullup() method, switches over
 to devm_request_irq(), adds support for DMA Engine and
 got a few miscelaneous cleanups.
 
 The NCM gadget got an endianness fix and the Ethernet
 gadget a frame size fix.
 
 We're finally removing the g_file_storage gadget and
 sticking to g_mass_storage and the new tcm_usb_gadget
 gadgets since that was a huge duplicaton of effort anyway.
 
 While removing g_file_storage, we also had to fix a bunch
 of defconfigs which were still pointing to the old gadget.
 
 There's a big series getting us closer to being able to
 introduce our configfs interface. The series converts
 functions into loadable modules which will, eventually,
 be registered to the configfs interface.
 
 Other than that there's the usual typo fixes and miscelaneous
 cleanups all over the place.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJQnXPMAAoJEIaOsuA1yqREkygQALIuhY6veRPZoZJltuADeAOV
 h7lBkuseJxvlJsbMLnjqP5tw4W/haE1deGR+ee1ZItkPrERCX1++jkQ6hmm7e00R
 mvr8rI+n3eBHSKUO89tUfCaz5UBsTl0cowPWdTwxRrV4VRJ1wVBw/oII9sfyss03
 jDo+11DSjTGTB+Bz72p2NTkRiv9my2Kz+ihhqFR5VSl5FyoutG53RNKRmciJKGB+
 i+RptOI+prdW1uOURHbie5FAI0xOBrE1Up2XdNiZ9blT6zcsK754Lc8erFJEZXX5
 7s8Ys/HJZLQCF/fRt4WAw8e1lSPELD2xuDMqV+WKu93aXOiAWL1SbzqK3Y+PaUDg
 Red07jOxgPqgq0F1mAp3+0Rs1RnshSvKREtQhZqsttg7suXhDB0q7h61CX8uQbRA
 hBZh8eFexRjqOZxveeV+h4ATz00c2nlEa8cJscr5zLf4R/LSxJWT7LV5227BDkBV
 9NUMA3dunDYZLqnxBv5lS2gQzmYO6G11wzdpgjnABL2WlM8Pv1lUDhY+erwvTRzd
 BM+9qMd7K40BuI1JyUsbBdmuEpJAD/yWE77pT2aBrr4767x0CYjBPZqQAxXFcWi8
 5NG1BzqWmH9HhwxKyWueWgNgY253cRcAzFlUN80NRA2UuNkMAeOAeJjvK48isAqJ
 T1MUkQgIFNvSecpRPrEl
 =umtl
 -----END PGP SIGNATURE-----

Merge tag 'gadget-for-v3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

USB gadget patches from Felipe:
"usb: gadget: patches for v3.8

renesas_usbhs implements ->pullup() method, switches over
to devm_request_irq(), adds support for DMA Engine and
got a few miscelaneous cleanups.

The NCM gadget got an endianness fix and the Ethernet
gadget a frame size fix.

We're finally removing the g_file_storage gadget and
sticking to g_mass_storage and the new tcm_usb_gadget
gadgets since that was a huge duplicaton of effort anyway.

While removing g_file_storage, we also had to fix a bunch
of defconfigs which were still pointing to the old gadget.

There's a big series getting us closer to being able to
introduce our configfs interface. The series converts
functions into loadable modules which will, eventually,
be registered to the configfs interface.

Other than that there's the usual typo fixes and miscelaneous
cleanups all over the place."
This commit is contained in:
Greg Kroah-Hartman 2012-11-11 17:31:53 -08:00
commit 7fd94beeca
84 changed files with 823 additions and 4793 deletions

View File

@ -671,7 +671,7 @@ than a kernel driver.
<para>There's a USB Mass Storage class driver, which provides
a different solution for interoperability with systems such
as MS-Windows and MacOS.
That <emphasis>File-backed Storage</emphasis> driver uses a
That <emphasis>Mass Storage</emphasis> driver uses a
file or block device as backing store for a drive,
like the <filename>loop</filename> driver.
The USB host uses the BBB, CB, or CBI versions of the mass

View File

@ -20,9 +20,9 @@
This document describes how to use the gadget from user space, its
relation to mass storage function (or MSF) and different gadgets
using it, and how it differs from File Storage Gadget (or FSG). It
will talk only briefly about how to use MSF within composite
gadgets.
using it, and how it differs from File Storage Gadget (or FSG)
(which is no longer included in Linux). It will talk only briefly
about how to use MSF within composite gadgets.
* Module parameters
@ -198,16 +198,15 @@
The Mass Storage Function and thus the Mass Storage Gadget has been
based on the File Storage Gadget. The difference between the two is
that MSG is a composite gadget (ie. uses the composite framework)
while file storage gadget is a traditional gadget. From userspace
while file storage gadget was a traditional gadget. From userspace
point of view this distinction does not really matter, but from
kernel hacker's point of view, this means that (i) MSG does not
duplicate code needed for handling basic USB protocol commands and
(ii) MSF can be used in any other composite gadget.
Because of that, File Storage Gadget has been deprecated and
scheduled to be removed in Linux 3.8. All users need to transition
to the Mass Storage Gadget by that time. The two gadgets behave
mostly the same from the outside except:
Because of that, File Storage Gadget has been removed in Linux 3.8.
All users need to transition to the Mass Storage Gadget. The two
gadgets behave mostly the same from the outside except:
1. In FSG the “removable” and “cdrom” module parameters set the flag
for all logical units whereas in MSG they accept a list of y/n

View File

@ -79,7 +79,7 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DEBUG=y

View File

@ -75,7 +75,7 @@ CONFIG_USB_STORAGE_DEBUG=y
CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_AT91SAM9=y

View File

@ -125,7 +125,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=m

View File

@ -133,7 +133,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_SDIO_UART=m

View File

@ -96,7 +96,7 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=m

View File

@ -218,7 +218,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_PXA=y

View File

@ -144,7 +144,7 @@ CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_USB_CDC_COMPOSITE=m

View File

@ -34,8 +34,7 @@ CONFIG_FB_MODE_HELPERS=y
CONFIG_USB_GADGET=m
CONFIG_USB_ZERO=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_FILE_STORAGE_TEST=y
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_EXT2_FS=y
CONFIG_TMPFS=y

View File

@ -136,7 +136,7 @@ CONFIG_USB_PXA27X=y
CONFIG_USB_ETH=m
# CONFIG_USB_ETH_RNDIS is not set
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_USB_GPIO_VBUS=y

View File

@ -240,7 +240,7 @@ CONFIG_USB_GADGET_S3C2410=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -214,8 +214,7 @@ CONFIG_USB_TEST=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
# CONFIG_USB_ETH_RNDIS is not set
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_FILE_STORAGE_TEST=y
CONFIG_USB_MASS_STORAGE=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y

View File

@ -37,7 +37,6 @@ CONFIG_SPI_SIRF=y
CONFIG_SPI_SPIDEV=y
# CONFIG_HWMON is not set
CONFIG_USB_GADGET=y
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y

View File

@ -214,7 +214,7 @@ CONFIG_USB_GADGET_DUMMY_HCD=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_PXA=y

View File

@ -97,7 +97,7 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=m
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y

View File

@ -139,7 +139,7 @@ CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_GADGET=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_RTC_CLASS=y

View File

@ -143,7 +143,7 @@ CONFIG_USB_GADGET=m
CONFIG_USB_PXA27X=y
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_MMC=y

View File

@ -109,7 +109,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -125,7 +125,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -124,7 +124,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -99,7 +99,7 @@ CONFIG_SND_ATMEL_AC97C=m
# CONFIG_SND_SPI is not set
CONFIG_USB_GADGET=m
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_ATMELMCI=y

View File

@ -111,7 +111,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -128,7 +128,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -127,7 +127,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=350
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -126,7 +126,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -105,7 +105,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -104,7 +104,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -129,7 +129,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -117,7 +117,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_CDC_COMPOSITE=m
CONFIG_MMC=y

View File

@ -127,7 +127,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=m
CONFIG_MMC_ATMELMCI=m

View File

@ -106,7 +106,7 @@ CONFIG_MUSB_PIO_ONLY=y
CONFIG_USB_STORAGE=m
CONFIG_USB_GADGET=m
CONFIG_USB_ETH=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_RTC_CLASS=y

View File

@ -107,7 +107,7 @@ CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
# CONFIG_USB_ETH_RNDIS is not set
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_MMC=m

View File

@ -83,7 +83,7 @@ CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_USB_GADGET=m
CONFIG_USB_ETH=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_PRINTER=m
CONFIG_MMC=y

View File

@ -473,7 +473,7 @@ CONFIG_USB_GADGET_NET2280=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_MIDI_GADGET=m
CONFIG_LEDS_CLASS=y

View File

@ -662,7 +662,7 @@ CONFIG_USB_GADGET_NET2280=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_MIDI_GADGET=m
CONFIG_MMC=m

View File

@ -112,7 +112,7 @@ CONFIG_USB_MON=y
CONFIG_USB_R8A66597_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_MMC=y
CONFIG_MMC_SPI=y
CONFIG_MMC_SDHI=y

View File

@ -109,7 +109,7 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_FILE_STORAGE=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_MMC=y
CONFIG_MMC_SPI=y

View File

@ -160,9 +160,6 @@ static ssize_t show_device(struct device *dev, struct device_attribute *attr,
gadget->speed);
n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed = %d\n",
gadget->max_speed);
/* TODO: Scheduled for removal in 3.8. */
n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n",
gadget_is_dualspeed(gadget));
n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n",
gadget->is_otg);
n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n",

View File

@ -721,31 +721,6 @@ config USB_FUNCTIONFS_GENERIC
Include a configuration with the Function Filesystem alone with
no Ethernet interface.
config USB_FILE_STORAGE
tristate "File-backed Storage Gadget (DEPRECATED)"
depends on BLOCK
help
The File-backed Storage Gadget acts as a USB Mass Storage
disk drive. As its storage repository it can use a regular
file or a block device (in much the same way as the "loop"
device driver), specified as a module parameter.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_file_storage".
NOTE: This driver is deprecated. Its replacement is the
Mass Storage Gadget.
config USB_FILE_STORAGE_TEST
bool "File-backed Storage Gadget testing version"
depends on USB_FILE_STORAGE
default n
help
Say "y" to generate the larger testing version of the
File-backed Storage Gadget, useful for probing the
behavior of USB Mass Storage hosts. Not needed for
normal operation.
config USB_MASS_STORAGE
tristate "Mass Storage Gadget"
depends on BLOCK
@ -756,8 +731,8 @@ config USB_MASS_STORAGE
device (in much the same way as the "loop" device driver),
specified as a module parameter or sysfs option.
This driver is an updated replacement for the deprecated
File-backed Storage Gadget (g_file_storage).
This driver is a replacement for now removed File-backed
Storage Gadget (g_file_storage).
Say "y" to link the driver statically, or "m" to build
a dynamically linked module called "g_mass_storage".

View File

@ -44,7 +44,6 @@ g_ether-y := ether.o
g_serial-y := serial.o
g_midi-y := gmidi.o
gadgetfs-y := inode.o
g_file_storage-y := file_storage.o
g_mass_storage-y := mass_storage.o
g_printer-y := printer.o
g_cdc-y := cdc2.o
@ -62,7 +61,6 @@ obj-$(CONFIG_USB_AUDIO) += g_audio.o
obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o

View File

@ -107,7 +107,7 @@ int config_ep_by_speed(struct usb_gadget *g,
}
/* else: fall through */
default:
speed_desc = f->descriptors;
speed_desc = f->fs_descriptors;
}
/* find descriptors */
for_each_ep_desc(speed_desc, d_spd) {
@ -200,7 +200,7 @@ int usb_add_function(struct usb_configuration *config,
* as full speed ... it's the function drivers that will need
* to avoid bulk and ISO transfers.
*/
if (!config->fullspeed && function->descriptors)
if (!config->fullspeed && function->fs_descriptors)
config->fullspeed = true;
if (!config->highspeed && function->hs_descriptors)
config->highspeed = true;
@ -363,7 +363,7 @@ static int config_buf(struct usb_configuration *config,
descriptors = f->hs_descriptors;
break;
default:
descriptors = f->descriptors;
descriptors = f->fs_descriptors;
}
if (!descriptors)
@ -620,7 +620,7 @@ static int set_config(struct usb_composite_dev *cdev,
descriptors = f->hs_descriptors;
break;
default:
descriptors = f->descriptors;
descriptors = f->fs_descriptors;
}
for (; *descriptors; ++descriptors) {

View File

@ -19,7 +19,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
@ -158,3 +158,40 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
return ret;
}
EXPORT_SYMBOL_GPL(usb_copy_descriptors);
int usb_assign_descriptors(struct usb_function *f,
struct usb_descriptor_header **fs,
struct usb_descriptor_header **hs,
struct usb_descriptor_header **ss)
{
struct usb_gadget *g = f->config->cdev->gadget;
if (fs) {
f->fs_descriptors = usb_copy_descriptors(fs);
if (!f->fs_descriptors)
goto err;
}
if (hs && gadget_is_dualspeed(g)) {
f->hs_descriptors = usb_copy_descriptors(hs);
if (!f->hs_descriptors)
goto err;
}
if (ss && gadget_is_superspeed(g)) {
f->ss_descriptors = usb_copy_descriptors(ss);
if (!f->ss_descriptors)
goto err;
}
return 0;
err:
usb_free_all_descriptors(f);
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(usb_assign_descriptors);
void usb_free_all_descriptors(struct usb_function *f)
{
usb_free_descriptors(f->fs_descriptors);
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->ss_descriptors);
}
EXPORT_SYMBOL_GPL(usb_free_all_descriptors);

View File

@ -63,16 +63,20 @@ MODULE_LICENSE("GPL");
struct dummy_hcd_module_parameters {
bool is_super_speed;
bool is_high_speed;
unsigned int num;
};
static struct dummy_hcd_module_parameters mod_data = {
.is_super_speed = false,
.is_high_speed = true,
.num = 1,
};
module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
module_param_named(num, mod_data.num, uint, S_IRUGO);
MODULE_PARM_DESC(num, "number of emulated controllers");
/*-------------------------------------------------------------------------*/
/* gadget side driver data structres */
@ -238,8 +242,6 @@ static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
return container_of(dev, struct dummy, gadget.dev);
}
static struct dummy the_controller;
/*-------------------------------------------------------------------------*/
/* SLAVE/GADGET SIDE UTILITY ROUTINES */
@ -973,9 +975,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
static int dummy_udc_probe(struct platform_device *pdev)
{
struct dummy *dum = &the_controller;
struct dummy *dum;
int rc;
dum = *((void **)dev_get_platdata(&pdev->dev));
dum->gadget.name = gadget_name;
dum->gadget.ops = &dummy_ops;
dum->gadget.max_speed = USB_SPEED_SUPER;
@ -2398,10 +2401,13 @@ static int dummy_h_get_frame(struct usb_hcd *hcd)
static int dummy_setup(struct usb_hcd *hcd)
{
struct dummy *dum;
dum = *((void **)dev_get_platdata(hcd->self.controller));
hcd->self.sg_tablesize = ~0;
if (usb_hcd_is_primary_hcd(hcd)) {
the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
the_controller.hs_hcd->dum = &the_controller;
dum->hs_hcd = hcd_to_dummy_hcd(hcd);
dum->hs_hcd->dum = dum;
/*
* Mark the first roothub as being USB 2.0.
* The USB 3.0 roothub will be registered later by
@ -2410,8 +2416,8 @@ static int dummy_setup(struct usb_hcd *hcd)
hcd->speed = HCD_USB2;
hcd->self.root_hub->speed = USB_SPEED_HIGH;
} else {
the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
the_controller.ss_hcd->dum = &the_controller;
dum->ss_hcd = hcd_to_dummy_hcd(hcd);
dum->ss_hcd->dum = dum;
hcd->speed = HCD_USB3;
hcd->self.root_hub->speed = USB_SPEED_SUPER;
}
@ -2524,11 +2530,13 @@ static struct hc_driver dummy_hcd = {
static int dummy_hcd_probe(struct platform_device *pdev)
{
struct dummy *dum;
struct usb_hcd *hs_hcd;
struct usb_hcd *ss_hcd;
int retval;
dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
dum = *((void **)dev_get_platdata(&pdev->dev));
if (!mod_data.is_super_speed)
dummy_hcd.flags = HCD_USB2;
@ -2561,7 +2569,7 @@ dealloc_usb2_hcd:
usb_remove_hcd(hs_hcd);
put_usb2_hcd:
usb_put_hcd(hs_hcd);
the_controller.hs_hcd = the_controller.ss_hcd = NULL;
dum->hs_hcd = dum->ss_hcd = NULL;
return retval;
}
@ -2579,8 +2587,8 @@ static int dummy_hcd_remove(struct platform_device *pdev)
usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
the_controller.hs_hcd = NULL;
the_controller.ss_hcd = NULL;
dum->hs_hcd = NULL;
dum->ss_hcd = NULL;
return 0;
}
@ -2627,13 +2635,15 @@ static struct platform_driver dummy_hcd_driver = {
};
/*-------------------------------------------------------------------------*/
static struct platform_device *the_udc_pdev;
static struct platform_device *the_hcd_pdev;
#define MAX_NUM_UDC 2
static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
static int __init init(void)
{
int retval = -ENOMEM;
int i;
struct dummy *dum[MAX_NUM_UDC];
if (usb_disabled())
return -ENODEV;
@ -2641,65 +2651,129 @@ static int __init init(void)
if (!mod_data.is_high_speed && mod_data.is_super_speed)
return -EINVAL;
the_hcd_pdev = platform_device_alloc(driver_name, -1);
if (!the_hcd_pdev)
return retval;
the_udc_pdev = platform_device_alloc(gadget_name, -1);
if (!the_udc_pdev)
goto err_alloc_udc;
if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
pr_err("Number of emulated UDC must be in range of 1…%d\n",
MAX_NUM_UDC);
return -EINVAL;
}
for (i = 0; i < mod_data.num; i++) {
the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
if (!the_hcd_pdev[i]) {
i--;
while (i >= 0)
platform_device_put(the_hcd_pdev[i--]);
return retval;
}
}
for (i = 0; i < mod_data.num; i++) {
the_udc_pdev[i] = platform_device_alloc(gadget_name, i);
if (!the_udc_pdev[i]) {
i--;
while (i >= 0)
platform_device_put(the_udc_pdev[i--]);
goto err_alloc_udc;
}
}
for (i = 0; i < mod_data.num; i++) {
dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
if (!dum[i])
goto err_add_pdata;
retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
sizeof(void *));
if (retval)
goto err_add_pdata;
retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
sizeof(void *));
if (retval)
goto err_add_pdata;
}
retval = platform_driver_register(&dummy_hcd_driver);
if (retval < 0)
goto err_register_hcd_driver;
goto err_add_pdata;
retval = platform_driver_register(&dummy_udc_driver);
if (retval < 0)
goto err_register_udc_driver;
retval = platform_device_add(the_hcd_pdev);
if (retval < 0)
goto err_add_hcd;
if (!the_controller.hs_hcd ||
(!the_controller.ss_hcd && mod_data.is_super_speed)) {
/*
* The hcd was added successfully but its probe function failed
* for some reason.
*/
retval = -EINVAL;
goto err_add_udc;
for (i = 0; i < mod_data.num; i++) {
retval = platform_device_add(the_hcd_pdev[i]);
if (retval < 0) {
i--;
while (i >= 0)
platform_device_del(the_hcd_pdev[i--]);
goto err_add_hcd;
}
}
retval = platform_device_add(the_udc_pdev);
if (retval < 0)
goto err_add_udc;
if (!platform_get_drvdata(the_udc_pdev)) {
/*
* The udc was added successfully but its probe function failed
* for some reason.
*/
retval = -EINVAL;
goto err_probe_udc;
for (i = 0; i < mod_data.num; i++) {
if (!dum[i]->hs_hcd ||
(!dum[i]->ss_hcd && mod_data.is_super_speed)) {
/*
* The hcd was added successfully but its probe
* function failed for some reason.
*/
retval = -EINVAL;
goto err_add_udc;
}
}
for (i = 0; i < mod_data.num; i++) {
retval = platform_device_add(the_udc_pdev[i]);
if (retval < 0) {
i--;
while (i >= 0)
platform_device_del(the_udc_pdev[i]);
goto err_add_udc;
}
}
for (i = 0; i < mod_data.num; i++) {
if (!platform_get_drvdata(the_udc_pdev[i])) {
/*
* The udc was added successfully but its probe
* function failed for some reason.
*/
retval = -EINVAL;
goto err_probe_udc;
}
}
return retval;
err_probe_udc:
platform_device_del(the_udc_pdev);
for (i = 0; i < mod_data.num; i++)
platform_device_del(the_udc_pdev[i]);
err_add_udc:
platform_device_del(the_hcd_pdev);
for (i = 0; i < mod_data.num; i++)
platform_device_del(the_hcd_pdev[i]);
err_add_hcd:
platform_driver_unregister(&dummy_udc_driver);
err_register_udc_driver:
platform_driver_unregister(&dummy_hcd_driver);
err_register_hcd_driver:
platform_device_put(the_udc_pdev);
err_add_pdata:
for (i = 0; i < mod_data.num; i++)
kfree(dum[i]);
for (i = 0; i < mod_data.num; i++)
platform_device_put(the_udc_pdev[i]);
err_alloc_udc:
platform_device_put(the_hcd_pdev);
for (i = 0; i < mod_data.num; i++)
platform_device_put(the_hcd_pdev[i]);
return retval;
}
module_init(init);
static void __exit cleanup(void)
{
platform_device_unregister(the_udc_pdev);
platform_device_unregister(the_hcd_pdev);
int i;
for (i = 0; i < mod_data.num; i++) {
struct dummy *dum;
dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
platform_device_unregister(the_udc_pdev[i]);
platform_device_unregister(the_hcd_pdev[i]);
kfree(dum);
}
platform_driver_unregister(&dummy_udc_driver);
platform_driver_unregister(&dummy_hcd_driver);
}

View File

@ -87,7 +87,7 @@ static inline struct f_acm *port_to_acm(struct gserial *p)
/* notification endpoint uses smallish and infrequent fixed-size messages */
#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
#define GS_NOTIFY_INTERVAL_MS 32
#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
/* interface and class descriptors: */
@ -167,7 +167,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
.bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
.bInterval = GS_NOTIFY_INTERVAL_MS,
};
static struct usb_endpoint_descriptor acm_fs_in_desc = {
@ -199,14 +199,13 @@ static struct usb_descriptor_header *acm_fs_function[] = {
};
/* high speed support: */
static struct usb_endpoint_descriptor acm_hs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
.bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
.bInterval = USB_MS_TO_HS_INTERVAL(GS_NOTIFY_INTERVAL_MS),
};
static struct usb_endpoint_descriptor acm_hs_in_desc = {
@ -659,37 +658,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
acm->notify_req->complete = acm_cdc_notify_complete;
acm->notify_req->context = acm;
/* copy descriptors */
f->descriptors = usb_copy_descriptors(acm_fs_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
acm_hs_in_desc.bEndpointAddress =
acm_fs_in_desc.bEndpointAddress;
acm_hs_out_desc.bEndpointAddress =
acm_fs_out_desc.bEndpointAddress;
acm_hs_notify_desc.bEndpointAddress =
acm_fs_notify_desc.bEndpointAddress;
acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
acm_hs_notify_desc.bEndpointAddress =
acm_fs_notify_desc.bEndpointAddress;
/* copy descriptors */
f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
}
if (gadget_is_superspeed(c->cdev->gadget)) {
acm_ss_in_desc.bEndpointAddress =
acm_fs_in_desc.bEndpointAddress;
acm_ss_out_desc.bEndpointAddress =
acm_fs_out_desc.bEndpointAddress;
acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
if (!f->ss_descriptors)
goto fail;
}
status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function,
acm_ss_function);
if (status)
goto fail;
DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
acm->port_num,
@ -721,11 +705,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
usb_free_descriptors(f->descriptors);
acm_string_defs[0].id = 0;
usb_free_all_descriptors(f);
gs_free_req(acm->notify, acm->notify_req);
kfree(acm);
}
@ -762,27 +743,15 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
*/
/* maybe allocate device-global string IDs, and patch descriptors */
if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
status = usb_string_id(c->cdev);
if (acm_string_defs[0].id == 0) {
status = usb_string_ids_tab(c->cdev, acm_string_defs);
if (status < 0)
return status;
acm_string_defs[ACM_CTRL_IDX].id = status;
acm_control_interface_desc.iInterface = status;
status = usb_string_id(c->cdev);
if (status < 0)
return status;
acm_string_defs[ACM_DATA_IDX].id = status;
acm_data_interface_desc.iInterface = status;
status = usb_string_id(c->cdev);
if (status < 0)
return status;
acm_string_defs[ACM_IAD_IDX].id = status;
acm_iad_descriptor.iFunction = status;
acm_control_interface_desc.iInterface =
acm_string_defs[ACM_CTRL_IDX].id;
acm_data_interface_desc.iInterface =
acm_string_defs[ACM_DATA_IDX].id;
acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
}
/* allocate and initialize one new instance */

View File

@ -91,7 +91,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
* encapsulated commands (vendor-specific, using control-OUT).
*/
#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
#define ECM_STATUS_INTERVAL_MS 32
#define ECM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
.bInterval = ECM_STATUS_INTERVAL_MS,
};
static struct usb_endpoint_descriptor fs_ecm_in_desc = {
@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
.bInterval = USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
};
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
@ -288,7 +288,7 @@ static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
.bInterval = USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
};
static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
@ -330,6 +330,7 @@ static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
static struct usb_descriptor_header *ecm_ss_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_iad_descriptor,
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
@ -353,7 +354,7 @@ static struct usb_descriptor_header *ecm_ss_function[] = {
static struct usb_string ecm_string_defs[] = {
[0].s = "CDC Ethernet Control Model (ECM)",
[1].s = NULL /* DYNAMIC */,
[1].s = "",
[2].s = "CDC Ethernet Data",
[3].s = "CDC ECM",
{ } /* end of list */
@ -742,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
ecm->notify_req->context = ecm;
ecm->notify_req->complete = ecm_notify_complete;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(ecm_fs_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_ecm_in_desc.bEndpointAddress =
fs_ecm_in_desc.bEndpointAddress;
hs_ecm_out_desc.bEndpointAddress =
fs_ecm_out_desc.bEndpointAddress;
hs_ecm_notify_desc.bEndpointAddress =
fs_ecm_notify_desc.bEndpointAddress;
hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
hs_ecm_notify_desc.bEndpointAddress =
fs_ecm_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
if (!f->hs_descriptors)
goto fail;
}
ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
ss_ecm_notify_desc.bEndpointAddress =
fs_ecm_notify_desc.bEndpointAddress;
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_ecm_in_desc.bEndpointAddress =
fs_ecm_in_desc.bEndpointAddress;
ss_ecm_out_desc.bEndpointAddress =
fs_ecm_out_desc.bEndpointAddress;
ss_ecm_notify_desc.bEndpointAddress =
fs_ecm_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(ecm_ss_function);
if (!f->ss_descriptors)
goto fail;
}
status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
ecm_ss_function);
if (status)
goto fail;
/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@ -795,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
if (f->descriptors)
usb_free_descriptors(f->descriptors);
if (f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
if (ecm->notify_req) {
kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req);
@ -808,9 +786,9 @@ fail:
/* we might as well release our claims on endpoints */
if (ecm->notify)
ecm->notify->driver_data = NULL;
if (ecm->port.out_ep->desc)
if (ecm->port.out_ep)
ecm->port.out_ep->driver_data = NULL;
if (ecm->port.in_ep->desc)
if (ecm->port.in_ep)
ecm->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@ -825,16 +803,11 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "ecm unbind\n");
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
ecm_string_defs[0].id = 0;
usb_free_all_descriptors(f);
kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req);
ecm_string_defs[1].s = NULL;
kfree(ecm);
}
@ -859,36 +832,15 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
return -EINVAL;
/* maybe allocate device-global string IDs */
if (ecm_string_defs[0].id == 0) {
/* control interface label */
status = usb_string_id(c->cdev);
if (status < 0)
status = usb_string_ids_tab(c->cdev, ecm_string_defs);
if (status)
return status;
ecm_string_defs[0].id = status;
ecm_control_intf.iInterface = status;
/* data interface label */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ecm_string_defs[2].id = status;
ecm_data_intf.iInterface = status;
/* MAC address */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ecm_string_defs[1].id = status;
ecm_desc.iMACAddress = status;
/* IAD label */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ecm_string_defs[3].id = status;
ecm_iad_descriptor.iFunction = status;
ecm_control_intf.iInterface = ecm_string_defs[0].id;
ecm_data_intf.iInterface = ecm_string_defs[2].id;
ecm_desc.iMACAddress = ecm_string_defs[1].id;
ecm_iad_descriptor.iFunction = ecm_string_defs[3].id;
}
/* allocate and initialize one new instance */
@ -913,9 +865,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
ecm->port.func.disable = ecm_disable;
status = usb_add_function(c, &ecm->port.func);
if (status) {
ecm_string_defs[1].s = NULL;
if (status)
kfree(ecm);
}
return status;
}

View File

@ -274,38 +274,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENOMEM;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(eem_fs_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
eem_hs_in_desc.bEndpointAddress =
eem_fs_in_desc.bEndpointAddress;
eem_hs_out_desc.bEndpointAddress =
eem_fs_out_desc.bEndpointAddress;
eem_hs_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
eem_hs_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(eem_hs_function);
if (!f->hs_descriptors)
goto fail;
}
eem_ss_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
if (gadget_is_superspeed(c->cdev->gadget)) {
eem_ss_in_desc.bEndpointAddress =
eem_fs_in_desc.bEndpointAddress;
eem_ss_out_desc.bEndpointAddress =
eem_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(eem_ss_function);
if (!f->ss_descriptors)
goto fail;
}
status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function,
eem_ss_function);
if (status)
goto fail;
DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
@ -314,15 +296,10 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
if (f->descriptors)
usb_free_descriptors(f->descriptors);
if (f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
/* we might as well release our claims on endpoints */
if (eem->port.out_ep->desc)
usb_free_all_descriptors(f);
if (eem->port.out_ep)
eem->port.out_ep->driver_data = NULL;
if (eem->port.in_ep->desc)
if (eem->port.in_ep)
eem->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@ -337,11 +314,7 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "eem unbind\n");
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
usb_free_all_descriptors(f);
kfree(eem);
}

View File

@ -2097,7 +2097,7 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
if (isHS)
func->function.hs_descriptors[(long)valuep] = desc;
else
func->function.descriptors[(long)valuep] = desc;
func->function.fs_descriptors[(long)valuep] = desc;
if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
return 0;
@ -2249,7 +2249,7 @@ static int ffs_func_bind(struct usb_configuration *c,
* numbers without worrying that it may be described later on.
*/
if (likely(full)) {
func->function.descriptors = data->fs_descs;
func->function.fs_descriptors = data->fs_descs;
ret = ffs_do_descs(ffs->fs_descs_count,
data->raw_descs,
sizeof data->raw_descs,

View File

@ -573,7 +573,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
hidg_interface_desc.bInterfaceNumber = status;
/* allocate instance-specific endpoints */
status = -ENODEV;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
@ -609,20 +608,15 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
hidg_desc.desc[0].wDescriptorLength =
cpu_to_le16(hidg->report_desc_length);
/* copy descriptors */
f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
if (!f->descriptors)
goto fail;
hidg_hs_in_ep_desc.bEndpointAddress =
hidg_fs_in_ep_desc.bEndpointAddress;
hidg_hs_out_ep_desc.bEndpointAddress =
hidg_fs_out_ep_desc.bEndpointAddress;
if (gadget_is_dualspeed(c->cdev->gadget)) {
hidg_hs_in_ep_desc.bEndpointAddress =
hidg_fs_in_ep_desc.bEndpointAddress;
hidg_hs_out_ep_desc.bEndpointAddress =
hidg_fs_out_ep_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
if (!f->hs_descriptors)
goto fail;
}
status = usb_assign_descriptors(f, hidg_fs_descriptors,
hidg_hs_descriptors, NULL);
if (status)
goto fail;
mutex_init(&hidg->lock);
spin_lock_init(&hidg->spinlock);
@ -649,9 +643,7 @@ fail:
usb_ep_free_request(hidg->in_ep, hidg->req);
}
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
usb_free_all_descriptors(f);
return status;
}
@ -668,9 +660,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
kfree(hidg->req->buf);
usb_ep_free_request(hidg->in_ep, hidg->req);
/* free descriptors copies */
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
usb_free_all_descriptors(f);
kfree(hidg->report_desc);
kfree(hidg);

View File

@ -177,6 +177,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_loopback *loop = func_to_loop(f);
int id;
int ret;
/* allocate interface ID(s) */
id = usb_interface_id(c, f);
@ -201,22 +202,19 @@ autoconf_fail:
loop->out_ep->driver_data = cdev; /* claim */
/* support high speed hardware */
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_loop_source_desc.bEndpointAddress =
fs_loop_source_desc.bEndpointAddress;
hs_loop_sink_desc.bEndpointAddress =
fs_loop_sink_desc.bEndpointAddress;
f->hs_descriptors = hs_loopback_descs;
}
hs_loop_source_desc.bEndpointAddress =
fs_loop_source_desc.bEndpointAddress;
hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
/* support super speed hardware */
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_loop_source_desc.bEndpointAddress =
fs_loop_source_desc.bEndpointAddress;
ss_loop_sink_desc.bEndpointAddress =
fs_loop_sink_desc.bEndpointAddress;
f->ss_descriptors = ss_loopback_descs;
}
ss_loop_source_desc.bEndpointAddress =
fs_loop_source_desc.bEndpointAddress;
ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
ss_loopback_descs);
if (ret)
return ret;
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
(gadget_is_superspeed(c->cdev->gadget) ? "super" :
@ -228,6 +226,7 @@ autoconf_fail:
static void
loopback_unbind(struct usb_configuration *c, struct usb_function *f)
{
usb_free_all_descriptors(f);
kfree(func_to_loop(f));
}
@ -379,7 +378,6 @@ static int __init loopback_bind_config(struct usb_configuration *c)
return -ENOMEM;
loop->function.name = "loopback";
loop->function.descriptors = fs_loopback_descs;
loop->function.bind = loopback_bind;
loop->function.unbind = loopback_unbind;
loop->function.set_alt = loopback_set_alt;

View File

@ -228,10 +228,6 @@
static const char fsg_string_interface[] = "Mass Storage";
#define FSG_NO_DEVICE_STRINGS 1
#define FSG_NO_OTG 1
#define FSG_NO_INTR_EP 1
#include "storage_common.c"
@ -2904,9 +2900,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
}
fsg_common_put(common);
usb_free_descriptors(fsg->function.descriptors);
usb_free_descriptors(fsg->function.hs_descriptors);
usb_free_descriptors(fsg->function.ss_descriptors);
usb_free_all_descriptors(&fsg->function);
kfree(fsg);
}
@ -2916,6 +2910,8 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_gadget *gadget = c->cdev->gadget;
int i;
struct usb_ep *ep;
unsigned max_burst;
int ret;
fsg->gadget = gadget;
@ -2939,45 +2935,27 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep;
/* Copy descriptors */
f->descriptors = usb_copy_descriptors(fsg_fs_function);
if (unlikely(!f->descriptors))
return -ENOMEM;
/* Assume endpoint addresses are the same for both speeds */
fsg_hs_bulk_in_desc.bEndpointAddress =
fsg_fs_bulk_in_desc.bEndpointAddress;
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
if (gadget_is_dualspeed(gadget)) {
/* Assume endpoint addresses are the same for both speeds */
fsg_hs_bulk_in_desc.bEndpointAddress =
fsg_fs_bulk_in_desc.bEndpointAddress;
fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
if (unlikely(!f->hs_descriptors)) {
usb_free_descriptors(f->descriptors);
return -ENOMEM;
}
}
/* Calculate bMaxBurst, we know packet size is 1024 */
max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
if (gadget_is_superspeed(gadget)) {
unsigned max_burst;
fsg_ss_bulk_in_desc.bEndpointAddress =
fsg_fs_bulk_in_desc.bEndpointAddress;
fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
/* Calculate bMaxBurst, we know packet size is 1024 */
max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
fsg_ss_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
fsg_ss_bulk_in_desc.bEndpointAddress =
fsg_fs_bulk_in_desc.bEndpointAddress;
fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
fsg_ss_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress;
fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
f->ss_descriptors = usb_copy_descriptors(fsg_ss_function);
if (unlikely(!f->ss_descriptors)) {
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
return -ENOMEM;
}
}
ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function,
fsg_ss_function);
if (ret)
goto autoconf_fail;
return 0;
@ -2986,7 +2964,6 @@ autoconf_fail:
return -ENOTSUPP;
}
/****************************** ADD FUNCTION ******************************/
static struct usb_gadget_strings *fsg_strings_array[] = {

View File

@ -414,7 +414,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
kfree(midi->id);
midi->id = NULL;
usb_free_descriptors(f->descriptors);
usb_free_all_descriptors(f);
kfree(midi);
}
@ -881,19 +881,25 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
* both speeds
*/
/* copy descriptors, and track endpoint copies */
f->fs_descriptors = usb_copy_descriptors(midi_function);
if (!f->fs_descriptors)
goto fail_f_midi;
if (gadget_is_dualspeed(c->cdev->gadget)) {
c->highspeed = true;
bulk_in_desc.wMaxPacketSize = cpu_to_le16(512);
bulk_out_desc.wMaxPacketSize = cpu_to_le16(512);
f->hs_descriptors = usb_copy_descriptors(midi_function);
} else {
f->descriptors = usb_copy_descriptors(midi_function);
if (!f->hs_descriptors)
goto fail_f_midi;
}
kfree(midi_function);
return 0;
fail_f_midi:
kfree(midi_function);
usb_free_descriptors(f->hs_descriptors);
fail:
/* we might as well release our claims on endpoints */
if (midi->out_ep)

View File

@ -102,7 +102,7 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)
USB_CDC_NCM_NTB32_SUPPORTED)
static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
.wLength = sizeof ntb_parameters,
.wLength = cpu_to_le16(sizeof(ntb_parameters)),
.bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
.dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
.wNdpInDivisor = cpu_to_le16(4),
@ -121,7 +121,7 @@ static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
* waste less bandwidth.
*/
#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
#define NCM_STATUS_INTERVAL_MS 32
#define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = {
@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT),
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
.bInterval = NCM_STATUS_INTERVAL_MS,
};
static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = {
@ -275,7 +275,7 @@ static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
.bInterval = USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS),
};
static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
@ -321,7 +321,7 @@ static struct usb_descriptor_header *ncm_hs_function[] __initdata = {
static struct usb_string ncm_string_defs[] = {
[STRING_CTRL_IDX].s = "CDC Network Control Model (NCM)",
[STRING_MAC_IDX].s = NULL /* DYNAMIC */,
[STRING_MAC_IDX].s = "",
[STRING_DATA_IDX].s = "CDC Network Data",
[STRING_IAD_IDX].s = "CDC NCM",
{ } /* end of list */
@ -869,15 +869,19 @@ static struct sk_buff *ncm_wrap_ntb(struct gether *port,
struct sk_buff *skb2;
int ncb_len = 0;
__le16 *tmp;
int div = ntb_parameters.wNdpInDivisor;
int rem = ntb_parameters.wNdpInPayloadRemainder;
int div;
int rem;
int pad;
int ndp_align = ntb_parameters.wNdpInAlignment;
int ndp_align;
int ndp_pad;
unsigned max_size = ncm->port.fixed_in_len;
struct ndp_parser_opts *opts = ncm->parser_opts;
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
ncb_len += opts->nth_size;
ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
ncb_len += ndp_pad;
@ -1208,30 +1212,18 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
ncm->notify_req->context = ncm;
ncm->notify_req->complete = ncm_notify_complete;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(ncm_fs_function);
if (!f->descriptors)
goto fail;
/*
* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_ncm_in_desc.bEndpointAddress =
fs_ncm_in_desc.bEndpointAddress;
hs_ncm_out_desc.bEndpointAddress =
fs_ncm_out_desc.bEndpointAddress;
hs_ncm_notify_desc.bEndpointAddress =
fs_ncm_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(ncm_hs_function);
if (!f->hs_descriptors)
goto fail;
}
hs_ncm_in_desc.bEndpointAddress = fs_ncm_in_desc.bEndpointAddress;
hs_ncm_out_desc.bEndpointAddress = fs_ncm_out_desc.bEndpointAddress;
hs_ncm_notify_desc.bEndpointAddress =
fs_ncm_notify_desc.bEndpointAddress;
status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
NULL);
/*
* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@ -1248,9 +1240,7 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
if (f->descriptors)
usb_free_descriptors(f->descriptors);
usb_free_all_descriptors(f);
if (ncm->notify_req) {
kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req);
@ -1259,9 +1249,9 @@ fail:
/* we might as well release our claims on endpoints */
if (ncm->notify)
ncm->notify->driver_data = NULL;
if (ncm->port.out_ep->desc)
if (ncm->port.out_ep)
ncm->port.out_ep->driver_data = NULL;
if (ncm->port.in_ep->desc)
if (ncm->port.in_ep)
ncm->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@ -1276,14 +1266,12 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "ncm unbind\n");
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
ncm_string_defs[0].id = 0;
usb_free_all_descriptors(f);
kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req);
ncm_string_defs[1].s = NULL;
kfree(ncm);
}
@ -1307,37 +1295,19 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
return -EINVAL;
/* maybe allocate device-global string IDs */
if (ncm_string_defs[0].id == 0) {
/* control interface label */
status = usb_string_id(c->cdev);
status = usb_string_ids_tab(c->cdev, ncm_string_defs);
if (status < 0)
return status;
ncm_string_defs[STRING_CTRL_IDX].id = status;
ncm_control_intf.iInterface = status;
ncm_control_intf.iInterface =
ncm_string_defs[STRING_CTRL_IDX].id;
/* data interface label */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ncm_string_defs[STRING_DATA_IDX].id = status;
status = ncm_string_defs[STRING_DATA_IDX].id;
ncm_data_nop_intf.iInterface = status;
ncm_data_intf.iInterface = status;
/* MAC address */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ncm_string_defs[STRING_MAC_IDX].id = status;
ecm_desc.iMACAddress = status;
/* IAD */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
ncm_string_defs[STRING_IAD_IDX].id = status;
ncm_iad_desc.iFunction = status;
ecm_desc.iMACAddress = ncm_string_defs[STRING_MAC_IDX].id;
ncm_iad_desc.iFunction = ncm_string_defs[STRING_IAD_IDX].id;
}
/* allocate and initialize one new instance */
@ -1347,7 +1317,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
/* export host's Ethernet address in CDC format */
snprintf(ncm->ethaddr, sizeof ncm->ethaddr, "%pm", ethaddr);
ncm_string_defs[1].s = ncm->ethaddr;
ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr;
spin_lock_init(&ncm->lock);
ncm_reset_values(ncm);
@ -1367,9 +1337,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
ncm->port.unwrap = ncm_unwrap_ntb;
status = usb_add_function(c, &ncm->port.func);
if (status) {
ncm_string_defs[1].s = NULL;
if (status)
kfree(ncm);
}
return status;
}

View File

@ -331,23 +331,19 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
obex->port.out = ep;
ep->driver_data = cdev; /* claim */
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(fs_function);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
obex_hs_ep_in_desc.bEndpointAddress =
obex_fs_ep_in_desc.bEndpointAddress;
obex_hs_ep_out_desc.bEndpointAddress =
obex_fs_ep_out_desc.bEndpointAddress;
obex_hs_ep_in_desc.bEndpointAddress =
obex_fs_ep_in_desc.bEndpointAddress;
obex_hs_ep_out_desc.bEndpointAddress =
obex_fs_ep_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(hs_function);
}
status = usb_assign_descriptors(f, fs_function, hs_function, NULL);
if (status)
goto fail;
/* Avoid letting this gadget enumerate until the userspace
* OBEX server is active.
@ -368,6 +364,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
usb_free_all_descriptors(f);
/* we might as well release our claims on endpoints */
if (obex->port.out)
obex->port.out->driver_data = NULL;
@ -382,9 +379,8 @@ fail:
static void
obex_unbind(struct usb_configuration *c, struct usb_function *f)
{
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
obex_string_defs[OBEX_CTRL_IDX].id = 0;
usb_free_all_descriptors(f);
kfree(func_to_obex(f));
}
@ -423,22 +419,16 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
if (!can_support_obex(c))
return -EINVAL;
/* maybe allocate device-global string IDs, and patch descriptors */
if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
status = usb_string_id(c->cdev);
status = usb_string_ids_tab(c->cdev, obex_string_defs);
if (status < 0)
return status;
obex_string_defs[OBEX_CTRL_IDX].id = status;
obex_control_intf.iInterface =
obex_string_defs[OBEX_CTRL_IDX].id;
obex_control_intf.iInterface = status;
status = usb_string_id(c->cdev);
if (status < 0)
return status;
obex_string_defs[OBEX_DATA_IDX].id = status;
obex_data_nop_intf.iInterface =
obex_data_intf.iInterface = status;
status = obex_string_defs[OBEX_DATA_IDX].id;
obex_data_nop_intf.iInterface = status;
obex_data_intf.iInterface = status;
}
/* allocate and initialize one new instance */

View File

@ -515,14 +515,14 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
fp->in_ep = ep;
ep->driver_data = fp; /* Claim */
pn_hs_sink_desc.bEndpointAddress =
pn_fs_sink_desc.bEndpointAddress;
pn_hs_source_desc.bEndpointAddress =
pn_fs_source_desc.bEndpointAddress;
pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress;
pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;
/* Do not try to bind Phonet twice... */
fp->function.descriptors = fs_pn_function;
fp->function.hs_descriptors = hs_pn_function;
status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function,
NULL);
if (status)
goto err;
/* Incoming USB requests */
status = -ENOMEM;
@ -531,7 +531,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL);
if (!req)
goto err;
goto err_req;
req->complete = pn_rx_complete;
fp->out_reqv[i] = req;
@ -540,14 +540,18 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
/* Outgoing USB requests */
fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL);
if (!fp->in_req)
goto err;
goto err_req;
INFO(cdev, "USB CDC Phonet function\n");
INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name,
fp->out_ep->name, fp->in_ep->name);
return 0;
err_req:
for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
err:
usb_free_all_descriptors(f);
if (fp->out_ep)
fp->out_ep->driver_data = NULL;
if (fp->in_ep)
@ -569,6 +573,7 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f)
if (fp->out_reqv[i])
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
usb_free_all_descriptors(f);
kfree(fp);
}

View File

@ -101,7 +101,7 @@ static unsigned int bitrate(struct usb_gadget *g)
/*
*/
#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
#define RNDIS_STATUS_INTERVAL_MS 32
#define STATUS_BYTECOUNT 8 /* 8 bytes data */
@ -190,7 +190,7 @@ static struct usb_endpoint_descriptor fs_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
.bInterval = RNDIS_STATUS_INTERVAL_MS,
};
static struct usb_endpoint_descriptor fs_in_desc = {
@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
.bInterval = USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)
};
static struct usb_endpoint_descriptor hs_in_desc = {
@ -284,7 +284,7 @@ static struct usb_endpoint_descriptor ss_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
.bInterval = USB_MS_TO_HS_INTERVAL(RNDIS_STATUS_INTERVAL_MS)
};
static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = {
@ -722,42 +722,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis->notify_req->context = rndis;
rndis->notify_req->complete = rndis_response_complete;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(eth_fs_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_in_desc.bEndpointAddress =
fs_in_desc.bEndpointAddress;
hs_out_desc.bEndpointAddress =
fs_out_desc.bEndpointAddress;
hs_notify_desc.bEndpointAddress =
fs_notify_desc.bEndpointAddress;
hs_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
hs_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
if (!f->hs_descriptors)
goto fail;
}
ss_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
ss_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_in_desc.bEndpointAddress =
fs_in_desc.bEndpointAddress;
ss_out_desc.bEndpointAddress =
fs_out_desc.bEndpointAddress;
ss_notify_desc.bEndpointAddress =
fs_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(eth_ss_function);
if (!f->ss_descriptors)
goto fail;
}
status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function,
eth_ss_function);
if (status)
goto fail;
rndis->port.open = rndis_open;
rndis->port.close = rndis_close;
@ -788,12 +768,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors)
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
if (f->descriptors)
usb_free_descriptors(f->descriptors);
usb_free_all_descriptors(f);
if (rndis->notify_req) {
kfree(rndis->notify_req->buf);
@ -803,9 +778,9 @@ fail:
/* we might as well release our claims on endpoints */
if (rndis->notify)
rndis->notify->driver_data = NULL;
if (rndis->port.out_ep->desc)
if (rndis->port.out_ep)
rndis->port.out_ep->driver_data = NULL;
if (rndis->port.in_ep->desc)
if (rndis->port.in_ep)
rndis->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@ -820,13 +795,9 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
rndis_deregister(rndis->config);
rndis_exit();
rndis_string_defs[0].id = 0;
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
rndis_string_defs[0].id = 0;
usb_free_all_descriptors(f);
kfree(rndis->notify_req->buf);
usb_ep_free_request(rndis->notify, rndis->notify_req);
@ -851,34 +822,19 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
if (!can_support_rndis(c) || !ethaddr)
return -EINVAL;
/* maybe allocate device-global string IDs */
if (rndis_string_defs[0].id == 0) {
/* ... and setup RNDIS itself */
status = rndis_init();
if (status < 0)
return status;
/* control interface label */
status = usb_string_id(c->cdev);
if (status < 0)
status = usb_string_ids_tab(c->cdev, rndis_string_defs);
if (status)
return status;
rndis_string_defs[0].id = status;
rndis_control_intf.iInterface = status;
/* data interface label */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
rndis_string_defs[1].id = status;
rndis_data_intf.iInterface = status;
/* IAD iFunction label */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
rndis_string_defs[2].id = status;
rndis_iad_descriptor.iFunction = status;
rndis_control_intf.iInterface = rndis_string_defs[0].id;
rndis_data_intf.iInterface = rndis_string_defs[1].id;
rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;
}
/* allocate and initialize one new instance */

View File

@ -213,34 +213,20 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
gser->port.out = ep;
ep->driver_data = cdev; /* claim */
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(gser_fs_function);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
gser_hs_in_desc.bEndpointAddress =
gser_fs_in_desc.bEndpointAddress;
gser_hs_out_desc.bEndpointAddress =
gser_fs_out_desc.bEndpointAddress;
gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
}
if (gadget_is_superspeed(c->cdev->gadget)) {
gser_ss_in_desc.bEndpointAddress =
gser_fs_in_desc.bEndpointAddress;
gser_ss_out_desc.bEndpointAddress =
gser_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
if (!f->ss_descriptors)
goto fail;
}
gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function,
gser_ss_function);
if (status)
goto fail;
DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
gser->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" :
@ -263,11 +249,7 @@ fail:
static void
gser_unbind(struct usb_configuration *c, struct usb_function *f)
{
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
usb_free_descriptors(f->descriptors);
usb_free_all_descriptors(f);
kfree(func_to_gser(f));
}

View File

@ -319,6 +319,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_sourcesink *ss = func_to_ss(f);
int id;
int ret;
/* allocate interface ID(s) */
id = usb_interface_id(c, f);
@ -387,64 +388,57 @@ no_iso:
isoc_maxpacket = 1024;
/* support high speed hardware */
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_source_desc.bEndpointAddress =
fs_source_desc.bEndpointAddress;
hs_sink_desc.bEndpointAddress =
fs_sink_desc.bEndpointAddress;
hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
/*
* Fill in the HS isoc descriptors from the module parameters.
* We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
hs_iso_source_desc.bInterval = isoc_interval;
hs_iso_source_desc.bEndpointAddress =
fs_iso_source_desc.bEndpointAddress;
/*
* Fill in the HS isoc descriptors from the module parameters.
* We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
hs_iso_source_desc.bInterval = isoc_interval;
hs_iso_source_desc.bEndpointAddress =
fs_iso_source_desc.bEndpointAddress;
hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
hs_iso_sink_desc.bInterval = isoc_interval;
hs_iso_sink_desc.bEndpointAddress =
fs_iso_sink_desc.bEndpointAddress;
f->hs_descriptors = hs_source_sink_descs;
}
hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
hs_iso_sink_desc.bInterval = isoc_interval;
hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
/* support super speed hardware */
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_source_desc.bEndpointAddress =
fs_source_desc.bEndpointAddress;
ss_sink_desc.bEndpointAddress =
fs_sink_desc.bEndpointAddress;
ss_source_desc.bEndpointAddress =
fs_source_desc.bEndpointAddress;
ss_sink_desc.bEndpointAddress =
fs_sink_desc.bEndpointAddress;
/*
* Fill in the SS isoc descriptors from the module parameters.
* We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
ss_iso_source_desc.bInterval = isoc_interval;
ss_iso_source_comp_desc.bmAttributes = isoc_mult;
ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
ss_iso_source_comp_desc.wBytesPerInterval =
isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
ss_iso_source_desc.bEndpointAddress =
fs_iso_source_desc.bEndpointAddress;
/*
* Fill in the SS isoc descriptors from the module parameters.
* We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
ss_iso_source_desc.bInterval = isoc_interval;
ss_iso_source_comp_desc.bmAttributes = isoc_mult;
ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
ss_iso_source_comp_desc.wBytesPerInterval =
isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
ss_iso_source_desc.bEndpointAddress =
fs_iso_source_desc.bEndpointAddress;
ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
ss_iso_sink_desc.bInterval = isoc_interval;
ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
ss_iso_sink_comp_desc.wBytesPerInterval =
isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
ss_iso_sink_desc.bEndpointAddress =
fs_iso_sink_desc.bEndpointAddress;
ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
ss_iso_sink_desc.bInterval = isoc_interval;
ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
ss_iso_sink_comp_desc.wBytesPerInterval =
isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
f->ss_descriptors = ss_source_sink_descs;
}
ret = usb_assign_descriptors(f, fs_source_sink_descs,
hs_source_sink_descs, ss_source_sink_descs);
if (ret)
return ret;
DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
(gadget_is_superspeed(c->cdev->gadget) ? "super" :
@ -458,6 +452,7 @@ no_iso:
static void
sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
{
usb_free_all_descriptors(f);
kfree(func_to_ss(f));
}
@ -773,7 +768,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
return -ENOMEM;
ss->function.name = "source/sink";
ss->function.descriptors = fs_source_sink_descs;
ss->function.bind = sourcesink_bind;
ss->function.unbind = sourcesink_unbind;
ss->function.set_alt = sourcesink_set_alt;

View File

@ -236,7 +236,7 @@ static struct usb_descriptor_header *ss_eth_function[] = {
static struct usb_string geth_string_defs[] = {
[0].s = "CDC Ethernet Subset/SAFE",
[1].s = NULL /* DYNAMIC */,
[1].s = "",
{ } /* end of list */
};
@ -319,38 +319,22 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
geth->port.out_ep = ep;
ep->driver_data = cdev; /* claim */
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(fs_eth_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_subset_in_desc.bEndpointAddress =
fs_subset_in_desc.bEndpointAddress;
hs_subset_out_desc.bEndpointAddress =
fs_subset_out_desc.bEndpointAddress;
hs_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
hs_subset_out_desc.bEndpointAddress =
fs_subset_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
if (!f->hs_descriptors)
goto fail;
}
ss_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
ss_subset_out_desc.bEndpointAddress =
fs_subset_out_desc.bEndpointAddress;
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_subset_in_desc.bEndpointAddress =
fs_subset_in_desc.bEndpointAddress;
ss_subset_out_desc.bEndpointAddress =
fs_subset_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(ss_eth_function);
if (!f->ss_descriptors)
goto fail;
}
status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function,
ss_eth_function);
if (status)
goto fail;
/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@ -364,15 +348,11 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
if (f->descriptors)
usb_free_descriptors(f->descriptors);
if (f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
usb_free_all_descriptors(f);
/* we might as well release our claims on endpoints */
if (geth->port.out_ep->desc)
if (geth->port.out_ep)
geth->port.out_ep->driver_data = NULL;
if (geth->port.in_ep->desc)
if (geth->port.in_ep)
geth->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@ -383,12 +363,8 @@ fail:
static void
geth_unbind(struct usb_configuration *c, struct usb_function *f)
{
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
geth_string_defs[1].s = NULL;
geth_string_defs[0].id = 0;
usb_free_all_descriptors(f);
kfree(func_to_geth(f));
}
@ -414,20 +390,11 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
/* maybe allocate device-global string IDs */
if (geth_string_defs[0].id == 0) {
/* interface label */
status = usb_string_id(c->cdev);
status = usb_string_ids_tab(c->cdev, geth_string_defs);
if (status < 0)
return status;
geth_string_defs[0].id = status;
subset_data_intf.iInterface = status;
/* MAC address */
status = usb_string_id(c->cdev);
if (status < 0)
return status;
geth_string_defs[1].id = status;
ether_desc.iMACAddress = status;
subset_data_intf.iInterface = geth_string_defs[0].id;
ether_desc.iMACAddress = geth_string_defs[1].id;
}
/* allocate and initialize one new instance */
@ -449,9 +416,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
geth->port.func.disable = geth_disable;
status = usb_add_function(c, &geth->port.func);
if (status) {
geth_string_defs[1].s = NULL;
if (status)
kfree(geth);
}
return status;
}

View File

@ -630,7 +630,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_audio *audio = func_to_audio(f);
int status;
struct usb_ep *ep;
struct usb_ep *ep = NULL;
f_audio_build_desc(audio);
@ -659,22 +659,14 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENOMEM;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(f_audio_desc);
/*
* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
c->highspeed = true;
f->hs_descriptors = usb_copy_descriptors(f_audio_desc);
}
status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL);
if (status)
goto fail;
return 0;
fail:
if (ep)
ep->driver_data = NULL;
return status;
}
@ -683,8 +675,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_audio *audio = func_to_audio(f);
usb_free_descriptors(f->descriptors);
usb_free_descriptors(f->hs_descriptors);
usb_free_all_descriptors(f);
kfree(audio);
}

View File

@ -50,13 +50,6 @@ static int c_ssize = 2;
module_param(c_ssize, uint, S_IRUGO);
MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)");
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define ALT_SET(x, a) do {(x) &= ~0xff; (x) |= (a); } while (0)
#define ALT_GET(x) ((x) & 0xff)
#define INTF_SET(x, i) do {(x) &= 0xff; (x) |= ((i) << 8); } while (0)
#define INTF_GET(x) ((x >> 8) & 0xff)
/* Keep everyone on toes */
#define USB_XFERS 2
@ -144,8 +137,9 @@ static struct snd_pcm_hardware uac2_pcm_hardware = {
};
struct audio_dev {
/* Currently active {Interface[15:8] | AltSettings[7:0]} */
__u16 ac_alt, as_out_alt, as_in_alt;
u8 ac_intf, ac_alt;
u8 as_out_intf, as_out_alt;
u8 as_in_intf, as_in_alt;
struct usb_ep *in_ep, *out_ep;
struct usb_function func;
@ -526,32 +520,22 @@ enum {
STR_AS_IN_ALT1,
};
static const char ifassoc[] = "Source/Sink";
static const char ifctrl[] = "Topology Control";
static char clksrc_in[8];
static char clksrc_out[8];
static const char usb_it[] = "USBH Out";
static const char io_it[] = "USBD Out";
static const char usb_ot[] = "USBH In";
static const char io_ot[] = "USBD In";
static const char out_alt0[] = "Playback Inactive";
static const char out_alt1[] = "Playback Active";
static const char in_alt0[] = "Capture Inactive";
static const char in_alt1[] = "Capture Active";
static struct usb_string strings_fn[] = {
[STR_ASSOC].s = ifassoc,
[STR_IF_CTRL].s = ifctrl,
[STR_ASSOC].s = "Source/Sink",
[STR_IF_CTRL].s = "Topology Control",
[STR_CLKSRC_IN].s = clksrc_in,
[STR_CLKSRC_OUT].s = clksrc_out,
[STR_USB_IT].s = usb_it,
[STR_IO_IT].s = io_it,
[STR_USB_OT].s = usb_ot,
[STR_IO_OT].s = io_ot,
[STR_AS_OUT_ALT0].s = out_alt0,
[STR_AS_OUT_ALT1].s = out_alt1,
[STR_AS_IN_ALT0].s = in_alt0,
[STR_AS_IN_ALT1].s = in_alt1,
[STR_USB_IT].s = "USBH Out",
[STR_IO_IT].s = "USBD Out",
[STR_USB_OT].s = "USBH In",
[STR_IO_OT].s = "USBD In",
[STR_AS_OUT_ALT0].s = "Playback Inactive",
[STR_AS_OUT_ALT1].s = "Playback Active",
[STR_AS_IN_ALT0].s = "Capture Inactive",
[STR_AS_IN_ALT1].s = "Capture Active",
{ },
};
@ -952,8 +936,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
return ret;
}
std_ac_if_desc.bInterfaceNumber = ret;
ALT_SET(agdev->ac_alt, 0);
INTF_SET(agdev->ac_alt, ret);
agdev->ac_intf = ret;
agdev->ac_alt = 0;
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
@ -963,8 +947,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
}
std_as_out_if0_desc.bInterfaceNumber = ret;
std_as_out_if1_desc.bInterfaceNumber = ret;
ALT_SET(agdev->as_out_alt, 0);
INTF_SET(agdev->as_out_alt, ret);
agdev->as_out_intf = ret;
agdev->as_out_alt = 0;
ret = usb_interface_id(cfg, fn);
if (ret < 0) {
@ -974,19 +958,23 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
}
std_as_in_if0_desc.bInterfaceNumber = ret;
std_as_in_if1_desc.bInterfaceNumber = ret;
ALT_SET(agdev->as_in_alt, 0);
INTF_SET(agdev->as_in_alt, ret);
agdev->as_in_intf = ret;
agdev->as_in_alt = 0;
agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
if (!agdev->out_ep)
if (!agdev->out_ep) {
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
goto err;
}
agdev->out_ep->driver_data = agdev;
agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
if (!agdev->in_ep)
if (!agdev->in_ep) {
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
goto err;
}
agdev->in_ep->driver_data = agdev;
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
@ -994,9 +982,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
fn->descriptors = usb_copy_descriptors(fs_audio_desc);
if (gadget_is_dualspeed(gadget))
fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc);
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
if (ret)
goto err;
prm = &agdev->uac2.c_prm;
prm->max_psize = hs_epout_desc.wMaxPacketSize;
@ -1005,6 +993,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->max_psize = 0;
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
goto err;
}
prm = &agdev->uac2.p_prm;
@ -1014,17 +1003,28 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->max_psize = 0;
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
goto err;
}
return alsa_uac2_init(agdev);
ret = alsa_uac2_init(agdev);
if (ret)
goto err;
return 0;
err:
kfree(agdev->uac2.p_prm.rbuf);
kfree(agdev->uac2.c_prm.rbuf);
usb_free_all_descriptors(fn);
if (agdev->in_ep)
agdev->in_ep->driver_data = NULL;
if (agdev->out_ep)
agdev->out_ep->driver_data = NULL;
return -EINVAL;
}
static void
afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
{
struct audio_dev *agdev = func_to_agdev(fn);
struct usb_composite_dev *cdev = cfg->cdev;
struct usb_gadget *gadget = cdev->gadget;
struct uac2_rtd_params *prm;
alsa_uac2_exit(agdev);
@ -1034,10 +1034,7 @@ afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
prm = &agdev->uac2.c_prm;
kfree(prm->rbuf);
if (gadget_is_dualspeed(gadget))
usb_free_descriptors(fn->hs_descriptors);
usb_free_descriptors(fn->descriptors);
usb_free_all_descriptors(fn);
if (agdev->in_ep)
agdev->in_ep->driver_data = NULL;
@ -1064,7 +1061,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
return -EINVAL;
}
if (intf == INTF_GET(agdev->ac_alt)) {
if (intf == agdev->ac_intf) {
/* Control I/f has only 1 AltSetting - 0 */
if (alt) {
dev_err(&uac2->pdev.dev,
@ -1074,16 +1071,16 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
return 0;
}
if (intf == INTF_GET(agdev->as_out_alt)) {
if (intf == agdev->as_out_intf) {
ep = agdev->out_ep;
prm = &uac2->c_prm;
config_ep_by_speed(gadget, fn, ep);
ALT_SET(agdev->as_out_alt, alt);
} else if (intf == INTF_GET(agdev->as_in_alt)) {
agdev->as_out_alt = alt;
} else if (intf == agdev->as_in_intf) {
ep = agdev->in_ep;
prm = &uac2->p_prm;
config_ep_by_speed(gadget, fn, ep);
ALT_SET(agdev->as_in_alt, alt);
agdev->as_in_alt = alt;
} else {
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
@ -1117,7 +1114,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
prm->ureq[i].pp = prm;
req->zero = 0;
req->dma = DMA_ADDR_INVALID;
req->context = &prm->ureq[i];
req->length = prm->max_psize;
req->complete = agdev_iso_complete;
@ -1136,12 +1132,12 @@ afunc_get_alt(struct usb_function *fn, unsigned intf)
struct audio_dev *agdev = func_to_agdev(fn);
struct snd_uac2_chip *uac2 = &agdev->uac2;
if (intf == INTF_GET(agdev->ac_alt))
return ALT_GET(agdev->ac_alt);
else if (intf == INTF_GET(agdev->as_out_alt))
return ALT_GET(agdev->as_out_alt);
else if (intf == INTF_GET(agdev->as_in_alt))
return ALT_GET(agdev->as_in_alt);
if (intf == agdev->ac_intf)
return agdev->ac_alt;
else if (intf == agdev->as_out_intf)
return agdev->as_out_alt;
else if (intf == agdev->as_in_intf)
return agdev->as_in_alt;
else
dev_err(&uac2->pdev.dev,
"%s:%d Invalid Interface %d!\n",
@ -1157,10 +1153,10 @@ afunc_disable(struct usb_function *fn)
struct snd_uac2_chip *uac2 = &agdev->uac2;
free_ep(&uac2->p_prm, agdev->in_ep);
ALT_SET(agdev->as_in_alt, 0);
agdev->as_in_alt = 0;
free_ep(&uac2->c_prm, agdev->out_ep);
ALT_SET(agdev->as_out_alt, 0);
agdev->as_out_alt = 0;
}
static int
@ -1267,7 +1263,7 @@ setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)
u16 w_index = le16_to_cpu(cr->wIndex);
u8 intf = w_index & 0xff;
if (intf != INTF_GET(agdev->ac_alt)) {
if (intf != agdev->ac_intf) {
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
return -EOPNOTSUPP;
@ -1316,7 +1312,7 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
static int audio_bind_config(struct usb_configuration *cfg)
{
int id, res;
int res;
agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);
if (agdev_g == NULL) {
@ -1324,89 +1320,21 @@ static int audio_bind_config(struct usb_configuration *cfg)
return -ENOMEM;
}
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_ASSOC].id = id;
iad_desc.iFunction = id,
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_IF_CTRL].id = id;
std_ac_if_desc.iInterface = id,
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_CLKSRC_IN].id = id;
in_clk_src_desc.iClockSource = id,
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_CLKSRC_OUT].id = id;
out_clk_src_desc.iClockSource = id,
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_USB_IT].id = id;
usb_out_it_desc.iTerminal = id,
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_IO_IT].id = id;
io_in_it_desc.iTerminal = id;
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_USB_OT].id = id;
usb_in_ot_desc.iTerminal = id;
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_IO_OT].id = id;
io_out_ot_desc.iTerminal = id;
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_AS_OUT_ALT0].id = id;
std_as_out_if0_desc.iInterface = id;
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_AS_OUT_ALT1].id = id;
std_as_out_if1_desc.iInterface = id;
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_AS_IN_ALT0].id = id;
std_as_in_if0_desc.iInterface = id;
id = usb_string_id(cfg->cdev);
if (id < 0)
return id;
strings_fn[STR_AS_IN_ALT1].id = id;
std_as_in_if1_desc.iInterface = id;
res = usb_string_ids_tab(cfg->cdev, strings_fn);
if (res)
return res;
iad_desc.iFunction = strings_fn[STR_ASSOC].id;
std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id;
in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id;
out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id;
usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id;
io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id;
usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id;
io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id;
std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id;
std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id;
std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id;
std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id;
agdev_g->func.name = "uac2_func";
agdev_g->func.strings = fn_strings;

View File

@ -417,7 +417,6 @@ uvc_register_video(struct uvc_device *uvc)
return -ENOMEM;
video->parent = &cdev->gadget->dev;
video->minor = -1;
video->fops = &uvc_v4l2_fops;
video->release = video_device_release;
strncpy(video->name, cdev->gadget->name, sizeof(video->name));
@ -577,27 +576,15 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
INFO(cdev, "uvc_function_unbind\n");
if (uvc->vdev) {
if (uvc->vdev->minor == -1)
video_device_release(uvc->vdev);
else
video_unregister_device(uvc->vdev);
uvc->vdev = NULL;
}
video_unregister_device(uvc->vdev);
uvc->control_ep->driver_data = NULL;
uvc->video.ep->driver_data = NULL;
if (uvc->control_ep)
uvc->control_ep->driver_data = NULL;
if (uvc->video.ep)
uvc->video.ep->driver_data = NULL;
uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
if (uvc->control_req) {
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
}
kfree(f->descriptors);
kfree(f->hs_descriptors);
kfree(f->ss_descriptors);
usb_free_all_descriptors(f);
kfree(uvc);
}
@ -663,49 +650,40 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
/* sanity check the streaming endpoint module parameters */
if (streaming_maxpacket > 1024)
streaming_maxpacket = 1024;
/*
* Fill in the HS descriptors from the module parameters for the Video
* Streaming endpoint.
* NOTE: We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
uvc_hs_streaming_ep.bInterval = streaming_interval;
uvc_hs_streaming_ep.bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress;
/* Copy descriptors for FS. */
f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
/*
* Fill in the SS descriptors from the module parameters for the Video
* Streaming endpoint.
* NOTE: We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
uvc_ss_streaming_ep.bInterval = streaming_interval;
uvc_ss_streaming_comp.bmAttributes = streaming_mult;
uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
uvc_ss_streaming_comp.wBytesPerInterval =
streaming_maxpacket * (streaming_mult + 1) *
(streaming_maxburst + 1);
uvc_ss_streaming_ep.bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress;
/* support high speed hardware */
if (gadget_is_dualspeed(cdev->gadget)) {
/*
* Fill in the HS descriptors from the module parameters for the
* Video Streaming endpoint.
* NOTE: We assume that the user knows what they are doing and
* won't give parameters that their UDC doesn't support.
*/
uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
uvc_hs_streaming_ep.bInterval = streaming_interval;
uvc_hs_streaming_ep.bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress;
/* Copy descriptors. */
/* Copy descriptors */
f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
if (gadget_is_dualspeed(cdev->gadget))
f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
}
/* support super speed hardware */
if (gadget_is_superspeed(c->cdev->gadget)) {
/*
* Fill in the SS descriptors from the module parameters for the
* Video Streaming endpoint.
* NOTE: We assume that the user knows what they are doing and
* won't give parameters that their UDC doesn't support.
*/
uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
uvc_ss_streaming_ep.bInterval = streaming_interval;
uvc_ss_streaming_comp.bmAttributes = streaming_mult;
uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
uvc_ss_streaming_comp.wBytesPerInterval =
streaming_maxpacket * (streaming_mult + 1) *
(streaming_maxburst + 1);
uvc_ss_streaming_ep.bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress;
/* Copy descriptors. */
if (gadget_is_superspeed(c->cdev->gadget))
f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
}
/* Preallocate control endpoint request. */
uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
@ -740,7 +718,20 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
error:
uvc_function_unbind(c, f);
if (uvc->vdev)
video_device_release(uvc->vdev);
if (uvc->control_ep)
uvc->control_ep->driver_data = NULL;
if (uvc->video.ep)
uvc->video.ep->driver_data = NULL;
if (uvc->control_req) {
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
}
usb_free_all_descriptors(f);
return ret;
}
@ -808,25 +799,16 @@ uvc_bind_config(struct usb_configuration *c,
uvc->desc.hs_streaming = hs_streaming;
uvc->desc.ss_streaming = ss_streaming;
/* maybe allocate device-global string IDs, and patch descriptors */
/* Allocate string descriptor numbers. */
if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
/* Allocate string descriptor numbers. */
ret = usb_string_id(c->cdev);
if (ret < 0)
ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
if (ret)
goto error;
uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
uvc_iad.iFunction = ret;
ret = usb_string_id(c->cdev);
if (ret < 0)
goto error;
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
uvc_control_intf.iInterface = ret;
ret = usb_string_id(c->cdev);
if (ret < 0)
goto error;
uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
uvc_iad.iFunction =
uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
uvc_control_intf.iInterface =
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
uvc_streaming_intf_alt0.iInterface = ret;
uvc_streaming_intf_alt1.iInterface = ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -2126,7 +2126,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
tmp_reg = fsl_readl(&dr_regs->usbintr);
t = scnprintf(next, size,
"USB Intrrupt Enable Reg:\n"
"USB Interrupt Enable Reg:\n"
"Sleep Enable: %d SOF Received Enable: %d "
"Reset Enable: %d\n"
"System Error Enable: %d "

View File

@ -76,7 +76,6 @@ MODULE_LICENSE ("GPL");
/*----------------------------------------------------------------------*/
#define GADGETFS_MAGIC 0xaee71ee7
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
/* /dev/gadget/$CHIP represents ep0 and the whole device */
enum ep0_state {
@ -918,7 +917,6 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)
if (req->buf != dev->rbuf) {
kfree(req->buf);
req->buf = dev->rbuf;
req->dma = DMA_ADDR_INVALID;
}
req->complete = epio_complete;
dev->setup_out_ready = 0;
@ -1408,7 +1406,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
dev->setup_abort = 1;
req->buf = dev->rbuf;
req->dma = DMA_ADDR_INVALID;
req->context = NULL;
value = -EOPNOTSUPP;
switch (ctrl->bRequest) {

View File

@ -2399,7 +2399,7 @@ static void udc_handle_ep0_setup(struct lpc32xx_udc *udc)
if (i < 0) {
/* setup processing failed, force stall */
dev_err(udc->dev,
dev_dbg(udc->dev,
"req %02x.%02x protocol STALL; stat %d\n",
reqtype, req, i);
udc->ep0state = WAIT_FOR_SETUP;

View File

@ -9,7 +9,7 @@
* CODE STATUS HIGHLIGHTS
*
* This driver should work well with most "gadget" drivers, including
* the File Storage, Serial, and Ethernet/RNDIS gadget drivers
* the Mass Storage, Serial, and Ethernet/RNDIS gadget drivers
* as well as Gadget Zero and Gadgetfs.
*
* DMA is enabled by default. Drivers using transfer queues might use

View File

@ -983,8 +983,10 @@ static int __init printer_func_bind(struct usb_configuration *c,
{
struct printer_dev *dev = container_of(f, struct printer_dev, function);
struct usb_composite_dev *cdev = c->cdev;
struct usb_ep *in_ep, *out_ep;
struct usb_ep *in_ep;
struct usb_ep *out_ep = NULL;
int id;
int ret;
id = usb_interface_id(c, f);
if (id < 0)
@ -1010,6 +1012,11 @@ autoconf_fail:
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
ret = usb_assign_descriptors(f, fs_printer_function,
hs_printer_function, NULL);
if (ret)
return ret;
dev->in_ep = in_ep;
dev->out_ep = out_ep;
return 0;
@ -1018,6 +1025,7 @@ autoconf_fail:
static void printer_func_unbind(struct usb_configuration *c,
struct usb_function *f)
{
usb_free_all_descriptors(f);
}
static int printer_func_set_alt(struct usb_function *f,
@ -1110,8 +1118,6 @@ static int __init printer_bind_config(struct usb_configuration *c)
dev = &usb_printer_gadget;
dev->function.name = shortname;
dev->function.descriptors = fs_printer_function;
dev->function.hs_descriptors = hs_printer_function;
dev->function.bind = printer_func_bind;
dev->function.setup = printer_func_setup;
dev->function.unbind = printer_func_unbind;

View File

@ -418,7 +418,7 @@ struct udc_stats {
* @irq: udc irq
* @clk: udc clock
* @usb_gadget: udc gadget structure
* @driver: bound gadget (zero, g_ether, g_file_storage, ...)
* @driver: bound gadget (zero, g_ether, g_mass_storage, ...)
* @dev: device
* @mach: machine info, used to activate specific GPIO
* @transceiver: external transceiver to handle vbus sense and D+ pullup

View File

@ -11,30 +11,10 @@
* (at your option) any later version.
*/
/*
* This file requires the following identifiers used in USB strings to
* be defined (each of type pointer to char):
* - fsg_string_manufacturer -- name of the manufacturer
* - fsg_string_product -- name of the product
* - fsg_string_config -- name of the configuration
* - fsg_string_interface -- name of the interface
* The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
* macro is defined prior to including this file.
*/
/*
* When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and
* fsg_hs_intr_in_desc objects as well as
* FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES
* macros are not defined.
*
* When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER,
* FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not
* defined (as well as corresponding entries in string tables are
* missing) and FSG_STRING_INTERFACE has value of zero.
*
* When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
*/
/*
@ -78,34 +58,6 @@
#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args)
#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args)
/*
* Keep those macros in sync with those in
* include/linux/usb/composite.h or else GCC will complain. If they
* are identical (the same names of arguments, white spaces in the
* same places) GCC will allow redefinition otherwise (even if some
* white space is removed or added) warning will be issued.
*
* Those macros are needed here because File Storage Gadget does not
* include the composite.h header. For composite gadgets those macros
* are redundant since composite.h is included any way.
*
* One could check whether those macros are already defined (which
* would indicate composite.h had been included) or not (which would
* indicate we were in FSG) but this is not done because a warning is
* desired if definitions here differ from the ones in composite.h.
*
* We want the definitions to match and be the same in File Storage
* Gadget as well as Mass Storage Function (and so composite gadgets
* using MSF). If someone changes them in composite.h it will produce
* a warning in this file when building MSF.
*/
#define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args)
#define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args)
#define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args)
#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args)
#define INFO(d, fmt, args...) dev_info(&(d)->gadget->dev , fmt , ## args)
#ifdef DUMP_MSGS
@ -203,9 +155,12 @@ struct fsg_lun {
struct device dev;
};
#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL)
static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
{
return curlun->filp != NULL;
}
static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)
{
return container_of(dev, struct fsg_lun, dev);
}
@ -308,26 +263,10 @@ static inline u32 get_unaligned_be24(u8 *buf)
enum {
#ifndef FSG_NO_DEVICE_STRINGS
FSG_STRING_MANUFACTURER = 1,
FSG_STRING_PRODUCT,
FSG_STRING_SERIAL,
FSG_STRING_CONFIG,
#endif
FSG_STRING_INTERFACE
};
#ifndef FSG_NO_OTG
static struct usb_otg_descriptor
fsg_otg_desc = {
.bLength = sizeof fsg_otg_desc,
.bDescriptorType = USB_DT_OTG,
.bmAttributes = USB_OTG_SRP,
};
#endif
/* There is only one interface. */
static struct usb_interface_descriptor
@ -367,37 +306,10 @@ fsg_fs_bulk_out_desc = {
/* wMaxPacketSize set by autoconfiguration */
};
#ifndef FSG_NO_INTR_EP
static struct usb_endpoint_descriptor
fsg_fs_intr_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(2),
.bInterval = 32, /* frames -> 32 ms */
};
#ifndef FSG_NO_OTG
# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2
#else
# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1
#endif
#endif
static struct usb_descriptor_header *fsg_fs_function[] = {
#ifndef FSG_NO_OTG
(struct usb_descriptor_header *) &fsg_otg_desc,
#endif
(struct usb_descriptor_header *) &fsg_intf_desc,
(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
#ifndef FSG_NO_INTR_EP
(struct usb_descriptor_header *) &fsg_fs_intr_in_desc,
#endif
NULL,
};
@ -431,37 +343,11 @@ fsg_hs_bulk_out_desc = {
.bInterval = 1, /* NAK every 1 uframe */
};
#ifndef FSG_NO_INTR_EP
static struct usb_endpoint_descriptor
fsg_hs_intr_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(2),
.bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */
};
#ifndef FSG_NO_OTG
# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2
#else
# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1
#endif
#endif
static struct usb_descriptor_header *fsg_hs_function[] = {
#ifndef FSG_NO_OTG
(struct usb_descriptor_header *) &fsg_otg_desc,
#endif
(struct usb_descriptor_header *) &fsg_intf_desc,
(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
#ifndef FSG_NO_INTR_EP
(struct usb_descriptor_header *) &fsg_hs_intr_in_desc,
#endif
NULL,
};
@ -499,34 +385,6 @@ static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
/*.bMaxBurst = DYNAMIC, */
};
#ifndef FSG_NO_INTR_EP
static struct usb_endpoint_descriptor
fsg_ss_intr_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(2),
.bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */
};
static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = {
.bLength = sizeof(fsg_ss_bulk_in_comp_desc),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
.wBytesPerInterval = cpu_to_le16(2),
};
#ifndef FSG_NO_OTG
# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 2
#else
# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 1
#endif
#endif
static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = {
.bLength = USB_DT_USB_EXT_CAP_SIZE,
.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
@ -563,18 +421,11 @@ static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
};
static struct usb_descriptor_header *fsg_ss_function[] = {
#ifndef FSG_NO_OTG
(struct usb_descriptor_header *) &fsg_otg_desc,
#endif
(struct usb_descriptor_header *) &fsg_intf_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_out_desc,
(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
#ifndef FSG_NO_INTR_EP
(struct usb_descriptor_header *) &fsg_ss_intr_in_desc,
(struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc,
#endif
NULL,
};
@ -594,12 +445,6 @@ fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
static struct usb_string fsg_strings[] = {
#ifndef FSG_NO_DEVICE_STRINGS
{FSG_STRING_MANUFACTURER, fsg_string_manufacturer},
{FSG_STRING_PRODUCT, fsg_string_product},
{FSG_STRING_SERIAL, ""},
{FSG_STRING_CONFIG, fsg_string_config},
#endif
{FSG_STRING_INTERFACE, fsg_string_interface},
{}
};

View File

@ -1384,7 +1384,7 @@ static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
if (!nacl) {
printk(KERN_ERR "Unable to alocate struct usbg_nacl\n");
printk(KERN_ERR "Unable to allocate struct usbg_nacl\n");
return NULL;
}
@ -2139,6 +2139,7 @@ static struct usb_descriptor_header *uasp_fs_function_desc[] = {
(struct usb_descriptor_header *) &uasp_status_pipe_desc,
(struct usb_descriptor_header *) &uasp_fs_cmd_desc,
(struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
NULL,
};
static struct usb_descriptor_header *uasp_hs_function_desc[] = {
@ -2239,6 +2240,7 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_gadget *gadget = c->cdev->gadget;
struct usb_ep *ep;
int iface;
int ret;
iface = usb_interface_id(c, f);
if (iface < 0)
@ -2289,6 +2291,11 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
uasp_ss_status_desc.bEndpointAddress;
uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
ret = usb_assign_descriptors(f, uasp_fs_function_desc,
uasp_hs_function_desc, uasp_ss_function_desc);
if (ret)
goto ep_fail;
return 0;
ep_fail:
pr_err("Can't claim all required eps\n");
@ -2304,6 +2311,7 @@ static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_uas *fu = to_f_uas(f);
usb_free_all_descriptors(f);
kfree(fu);
}
@ -2384,9 +2392,6 @@ static int usbg_cfg_bind(struct usb_configuration *c)
if (!fu)
return -ENOMEM;
fu->function.name = "Target Function";
fu->function.descriptors = uasp_fs_function_desc;
fu->function.hs_descriptors = uasp_hs_function_desc;
fu->function.ss_descriptors = uasp_ss_function_desc;
fu->function.bind = usbg_bind;
fu->function.unbind = usbg_unbind;
fu->function.set_alt = usbg_set_alt;

View File

@ -20,6 +20,7 @@
#include <linux/ctype.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include "u_ether.h"
@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
while (skb2) {
if (status < 0
|| ETH_HLEN > skb2->len
|| skb2->len > ETH_FRAME_LEN) {
|| skb2->len > VLAN_ETH_FRAME_LEN) {
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
DBG(dev, "rx length %d\n", skb2->len);

View File

@ -439,16 +439,6 @@ static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
static USB_UDC_SPEED_ATTR(current_speed, speed);
static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
/* TODO: Scheduled for removal in 3.8. */
static ssize_t usb_udc_is_dualspeed_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
return snprintf(buf, PAGE_SIZE, "%d\n",
gadget_is_dualspeed(udc->gadget));
}
static DEVICE_ATTR(is_dualspeed, S_IRUSR, usb_udc_is_dualspeed_show, NULL);
#define USB_UDC_ATTR(name) \
ssize_t usb_udc_##name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
@ -472,7 +462,6 @@ static struct attribute *usb_udc_attrs[] = {
&dev_attr_current_speed.attr,
&dev_attr_maximum_speed.attr,
&dev_attr_is_dualspeed.attr,
&dev_attr_is_otg.attr,
&dev_attr_is_a_peripheral.attr,
&dev_attr_b_hnp_enable.attr,

View File

@ -332,7 +332,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
* Also, DRVVBUS pulses for SRP (but not at 5V) ...
*/
if (usbintr & MUSB_INTR_BABBLE)
pr_info("CAUTION: musb: Babble Interrupt Occured\n");
pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
int drvvbus = dsps_readl(reg_base, wrp->status);

View File

@ -132,6 +132,11 @@ void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
}
void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable)
{
usbhs_bset(priv, SYSCFG, DPRPU, enable ? DPRPU : 0);
}
void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode)
{
usbhs_write(priv, TESTMODE, mode);

View File

@ -285,6 +285,7 @@ void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data);
*/
void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable);
void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable);
void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable);
void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode);
/*

View File

@ -163,7 +163,7 @@ static int usbhsf_pkt_handler(struct usbhs_pipe *pipe, int type)
func = pkt->handler->dma_done;
break;
default:
dev_err(dev, "unknown pkt hander\n");
dev_err(dev, "unknown pkt handler\n");
goto __usbhs_pkt_handler_end;
}
@ -192,8 +192,8 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)
/*
* irq enable/disable function
*/
#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, bempsts, e)
#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, brdysts, e)
#define usbhsf_irq_empty_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_bempsts, e)
#define usbhsf_irq_ready_ctrl(p, e) usbhsf_irq_callback_ctrl(p, irq_brdysts, e)
#define usbhsf_irq_callback_ctrl(pipe, status, enable) \
({ \
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); \
@ -202,9 +202,9 @@ void usbhs_pkt_start(struct usbhs_pipe *pipe)
if (!mod) \
return; \
if (enable) \
mod->irq_##status |= status; \
mod->status |= status; \
else \
mod->irq_##status &= ~status; \
mod->status &= ~status; \
usbhs_irq_callback_update(priv, mod); \
})
@ -488,6 +488,8 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
usbhs_pipe_data_sequence(pipe, pkt->sequence);
pkt->sequence = -1; /* -1 sequence will be ignored */
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
ret = usbhsf_fifo_select(pipe, fifo, 1);
if (ret < 0)
return 0;
@ -594,6 +596,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
usbhs_pipe_data_sequence(pipe, pkt->sequence);
pkt->sequence = -1; /* -1 sequence will be ignored */
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
usbhs_pipe_enable(pipe);
usbhsf_rx_irq_ctrl(pipe, 1);
@ -795,6 +798,7 @@ static void xfer_work(struct work_struct *work)
dev_dbg(dev, " %s %d (%d/ %d)\n",
fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
usbhs_pipe_enable(pipe);
usbhsf_dma_start(pipe, fifo);
dma_async_issue_pending(chan);

View File

@ -151,7 +151,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
goto mod_init_host_err;
/* irq settings */
ret = request_irq(priv->irq, usbhs_interrupt,
ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
priv->irqflags, dev_name(dev), priv);
if (ret) {
dev_err(dev, "irq request err\n");
@ -172,7 +172,6 @@ void usbhs_mod_remove(struct usbhs_priv *priv)
{
usbhs_mod_host_remove(priv);
usbhs_mod_gadget_remove(priv);
free_irq(priv->irq, priv);
}
/*

View File

@ -883,6 +883,16 @@ static int usbhsg_get_frame(struct usb_gadget *gadget)
return usbhs_frame_get_num(priv);
}
static int usbhsg_pullup(struct usb_gadget *gadget, int is_on)
{
struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
usbhs_sys_function_pullup(priv, is_on);
return 0;
}
static int usbhsg_set_selfpowered(struct usb_gadget *gadget, int is_self)
{
struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
@ -900,6 +910,7 @@ static struct usb_gadget_ops usbhsg_gadget_ops = {
.set_selfpowered = usbhsg_set_selfpowered,
.udc_start = usbhsg_gadget_start,
.udc_stop = usbhsg_gadget_stop,
.pullup = usbhsg_pullup,
};
static int usbhsg_start(struct usbhs_priv *priv)

View File

@ -85,6 +85,7 @@ struct usbhsh_ep {
struct usbhsh_device *udev; /* attached udev */
struct usb_host_endpoint *ep;
struct list_head ep_list; /* list to usbhsh_device */
unsigned int counter; /* pipe attach counter */
};
#define USBHSH_DEVICE_MAX 10 /* see DEVADDn / DCPMAXP / PIPEMAXP */
@ -271,8 +272,12 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
/******************** spin lock ********************/
usbhs_lock(priv, flags);
if (unlikely(usbhsh_uep_to_pipe(uep))) {
dev_err(dev, "uep already has pipe\n");
/*
* if uep has been attached to pipe,
* reuse it
*/
if (usbhsh_uep_to_pipe(uep)) {
ret = 0;
goto usbhsh_pipe_attach_done;
}
@ -320,6 +325,9 @@ static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
}
usbhsh_pipe_attach_done:
if (0 == ret)
uep->counter++;
usbhs_unlock(priv, flags);
/******************** spin unlock ******************/
@ -346,7 +354,7 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
if (unlikely(!pipe)) {
dev_err(dev, "uep doens't have pipe\n");
} else {
} else if (1 == uep->counter--) { /* last user */
struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep);
struct usbhsh_device *udev = usbhsh_uep_to_udev(uep);
@ -391,6 +399,7 @@ static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv,
/*
* init endpoint
*/
uep->counter = 0;
INIT_LIST_HEAD(&uep->ep_list);
list_add_tail(&uep->ep_list, &udev->ep_list_head);
@ -686,9 +695,9 @@ static int usbhsh_queue_push(struct usb_hcd *hcd,
}
if (usb_pipein(urb->pipe))
pipe->handler = &usbhs_fifo_pio_pop_handler;
pipe->handler = &usbhs_fifo_dma_pop_handler;
else
pipe->handler = &usbhs_fifo_pio_push_handler;
pipe->handler = &usbhs_fifo_dma_push_handler;
buf = (void *)(urb->transfer_buffer + urb->actual_length);
len = urb->transfer_buffer_length - urb->actual_length;
@ -921,6 +930,19 @@ static int usbhsh_dcp_queue_push(struct usb_hcd *hcd,
*/
static int usbhsh_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
{
if (map) {
struct usbhsh_request *ureq = usbhsh_pkt_to_ureq(pkt);
struct urb *urb = ureq->urb;
/* it can not use scatter/gather */
if (urb->num_sgs)
return -EINVAL;
pkt->dma = urb->transfer_dma;
if (!pkt->dma)
return -EINVAL;
}
return 0;
}
@ -946,7 +968,6 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
struct usb_host_endpoint *ep = urb->ep;
struct usbhsh_device *new_udev = NULL;
int is_dir_in = usb_pipein(urb->pipe);
int i;
int ret;
dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out");
@ -992,13 +1013,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
* attach pipe to endpoint
* see [image of mod_host]
*/
for (i = 0; i < 1024; i++) {
ret = usbhsh_pipe_attach(hpriv, urb);
if (ret < 0)
msleep(100);
else
break;
}
ret = usbhsh_pipe_attach(hpriv, urb);
if (ret < 0) {
dev_err(dev, "pipe attach failed\n");
goto usbhsh_urb_enqueue_error_free_endpoint;
@ -1072,8 +1087,6 @@ static void usbhsh_endpoint_disable(struct usb_hcd *hcd,
static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd);
struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
struct device *dev = usbhs_priv_to_dev(priv);
int roothub_id = 1; /* only 1 root hub */
/*
@ -1085,8 +1098,6 @@ static int usbhsh_hub_status_data(struct usb_hcd *hcd, char *buf)
else
*buf = 0;
dev_dbg(dev, "%s (%02x)\n", __func__, *buf);
return !!(*buf);
}

View File

@ -92,6 +92,82 @@ static void usbhsp_pipe_cfg_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
__usbhsp_pipe_xxx_set(pipe, DCPCFG, PIPECFG, mask, val);
}
/*
* PIPEnTRN/PIPEnTRE functions
*/
static void usbhsp_pipe_trn_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
{
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct device *dev = usbhs_priv_to_dev(priv);
int num = usbhs_pipe_number(pipe);
u16 reg;
/*
* It is impossible to calculate address,
* since PIPEnTRN addresses were mapped randomly.
*/
#define CASE_PIPExTRN(a) \
case 0x ## a: \
reg = PIPE ## a ## TRN; \
break;
switch (num) {
CASE_PIPExTRN(1);
CASE_PIPExTRN(2);
CASE_PIPExTRN(3);
CASE_PIPExTRN(4);
CASE_PIPExTRN(5);
CASE_PIPExTRN(B);
CASE_PIPExTRN(C);
CASE_PIPExTRN(D);
CASE_PIPExTRN(E);
CASE_PIPExTRN(F);
CASE_PIPExTRN(9);
CASE_PIPExTRN(A);
default:
dev_err(dev, "unknown pipe (%d)\n", num);
return;
}
__usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
}
static void usbhsp_pipe_tre_set(struct usbhs_pipe *pipe, u16 mask, u16 val)
{
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
struct device *dev = usbhs_priv_to_dev(priv);
int num = usbhs_pipe_number(pipe);
u16 reg;
/*
* It is impossible to calculate address,
* since PIPEnTRE addresses were mapped randomly.
*/
#define CASE_PIPExTRE(a) \
case 0x ## a: \
reg = PIPE ## a ## TRE; \
break;
switch (num) {
CASE_PIPExTRE(1);
CASE_PIPExTRE(2);
CASE_PIPExTRE(3);
CASE_PIPExTRE(4);
CASE_PIPExTRE(5);
CASE_PIPExTRE(B);
CASE_PIPExTRE(C);
CASE_PIPExTRE(D);
CASE_PIPExTRE(E);
CASE_PIPExTRE(F);
CASE_PIPExTRE(9);
CASE_PIPExTRE(A);
default:
dev_err(dev, "unknown pipe (%d)\n", num);
return;
}
__usbhsp_pipe_xxx_set(pipe, 0, reg, mask, val);
}
/*
* PIPEBUF
*/
@ -264,6 +340,31 @@ int usbhs_pipe_is_stall(struct usbhs_pipe *pipe)
return (int)(pid == PID_STALL10 || pid == PID_STALL11);
}
void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len)
{
if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
return;
/*
* clear and disable transfer counter for IN/OUT pipe
*/
usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR);
/*
* Only IN direction bulk pipe can use transfer count.
* Without using this function,
* received data will break if it was large data size.
* see PIPEnTRN/PIPEnTRE for detail
*/
if (usbhs_pipe_is_dir_in(pipe)) {
int maxp = usbhs_pipe_get_maxpacket(pipe);
usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp));
usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */
}
}
/*
* pipe setup
*/

View File

@ -88,6 +88,7 @@ void usbhs_pipe_enable(struct usbhs_pipe *pipe);
void usbhs_pipe_disable(struct usbhs_pipe *pipe);
void usbhs_pipe_stall(struct usbhs_pipe *pipe);
int usbhs_pipe_is_stall(struct usbhs_pipe *pipe);
void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len);
void usbhs_pipe_select_fifo(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo);
void usbhs_pipe_config_update(struct usbhs_pipe *pipe, u16 devsel,
u16 epnum, u16 maxp);

View File

@ -38,6 +38,7 @@
#include <linux/version.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/log2.h>
/*
* USB function drivers should return USB_GADGET_DELAYED_STATUS if they
@ -51,6 +52,7 @@
/* big enough to hold our biggest descriptor */
#define USB_COMP_EP0_BUFSIZ 1024
#define USB_MS_TO_HS_INTERVAL(x) (ilog2((x * 1000 / 125)) + 1)
struct usb_configuration;
/**
@ -117,7 +119,7 @@ struct usb_configuration;
struct usb_function {
const char *name;
struct usb_gadget_strings **strings;
struct usb_descriptor_header **descriptors;
struct usb_descriptor_header **fs_descriptors;
struct usb_descriptor_header **hs_descriptors;
struct usb_descriptor_header **ss_descriptors;

View File

@ -939,6 +939,13 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)
kfree(v);
}
struct usb_function;
int usb_assign_descriptors(struct usb_function *f,
struct usb_descriptor_header **fs,
struct usb_descriptor_header **hs,
struct usb_descriptor_header **ss);
void usb_free_all_descriptors(struct usb_function *f);
/*-------------------------------------------------------------------------*/
/* utility to simplify map/unmap of usb_requests to/from DMA */