forked from Minki/linux
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:
commit
7fd94beeca
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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".
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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[] = {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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 "
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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},
|
||||
{}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user