提交 f549953c 编写于 作者: L Linus Torvalds

Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (115 commits)
  EHCI: fix direction handling for interrupt data toggles
  USB: serial: add IDs for WinChipHead USB->RS232 adapter
  USB: OHCI: fix another regression for NVIDIA controllers
  usb: gadget: m66592-udc: add pullup function
  usb: gadget: m66592-udc: add function for external controller
  usb: gadget: r8a66597-udc: add pullup function
  usb: renesas_usbhs: support multi driver
  usb: renesas_usbhs: inaccessible pipe is not an error
  usb: renesas_usbhs: care buff alignment when dma handler
  USB: PL2303: correctly handle baudrates above 115200
  usb: r8a66597-hcd: fixup USB_PORT_STAT_C_SUSPEND shift
  usb: renesas_usbhs: compile/config are rescued
  usb: renesas_usbhs: fixup comment-out
  usb: update email address in ohci-sh and r8a66597-hcd
  usb: r8a66597-hcd: add function for external controller
  EHCI: only power off port if over-current is active
  USB: mon: Allow to use usbmon without debugfs
  USB: EHCI: go back to using the system clock for QH unlinks
  ehci: add pci quirk for Ordissimo and RM Slate 100 too
  ehci: refactor pci quirk to use standard dmi_check_system method
  ...

Fix up trivial conflicts in Documentation/feature-removal-schedule.txt
......@@ -10,3 +10,26 @@ KernelVersion: 2.6.35
Contact: masa-korg@dsn.okisemi.com
Description: Write/read Option ROM data.
What: /sys/module/ehci_hcd/drivers/.../uframe_periodic_max
Date: July 2011
KernelVersion: 3.1
Contact: Kirill Smelkov <kirr@mns.spb.ru>
Description: Maximum time allowed for periodic transfers per microframe (μs)
[ USB 2.0 sets maximum allowed time for periodic transfers per
microframe to be 80%, that is 100 microseconds out of 125
microseconds (full microframe).
However there are cases, when 80% max isochronous bandwidth is
too limiting. For example two video streams could require 110
microseconds of isochronous bandwidth per microframe to work
together. ]
Through this setting it is possible to raise the limit so that
the host controller would allow allocating more than 100
microseconds of periodic bandwidth per microframe.
Beware, non-standard modes are usually not thoroughly tested by
hardware designers, and the hardware can malfunction when this
setting differ from default 100.
......@@ -569,3 +569,10 @@ Why: Just opening a V4L device should not change the state of the hardware
Who: Hans Verkuil <hans.verkuil@cisco.com>
----------------------------
What: g_file_storage driver
When: 3.8
Why: This driver has been superseded by g_mass_storage.
Who: Alan Stern <stern@rowland.harvard.edu>
----------------------------
......@@ -2545,6 +2545,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
unknown_nmi_panic
[X86] Cause panic on unknown NMI.
usbcore.authorized_default=
[USB] Default USB device authorization:
(default -1 = authorized except for wireless USB,
0 = not authorized, 1 = authorized)
usbcore.autosuspend=
[USB] The autosuspend time delay (in seconds) used
for newly-detected USB devices (default 2). This
......
......@@ -210,3 +210,5 @@ TBD: Interrupt and ISO transfer performance issues. Those periodic
transfers are fully scheduled, so the main issue is likely to be how
to trigger "high bandwidth" modes.
TBD: More than standard 80% periodic bandwidth allocation is possible
through sysfs uframe_periodic_max parameter. Describe that.
......@@ -81,8 +81,8 @@ Send and receive HID reports
to do this.
hid_gadget_test is a small interactive program to test the HID
gadget driver. To use, point it at a hidg device and set the
device type (keyboard / mouse / joystick) - E.G.:
gadget driver. To use, point it at a hidg device and set the
device type (keyboard / mouse / joystick) - E.G.:
# hid_gadget_test /dev/hidg0 keyboard
......@@ -97,7 +97,7 @@ Send and receive HID reports
HID gadget.
Another interesting example is the caps lock test. Type
-caps-lock and hit return. A report is then sent by the
--caps-lock and hit return. A report is then sent by the
gadget and you should receive the host answer, corresponding
to the caps lock LED status.
......
......@@ -33,8 +33,6 @@
#include <plat/omap_device.h>
#include "mux.h"
#if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
static struct musb_hdrc_config musb_config = {
.multipoint = 1,
.dyn_fifo = 1,
......@@ -175,11 +173,3 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
if (cpu_is_omap44xx())
omap4430_phy_init(dev);
}
#else
void __init usb_musb_init(struct omap_musb_board_data *board_data)
{
if (cpu_is_omap44xx())
omap4430_phy_init(NULL);
}
#endif /* CONFIG_USB_MUSB_SOC */
......@@ -116,14 +116,14 @@ struct uea_cmvs_v1 {
u32 address;
u16 offset;
u32 data;
} __attribute__ ((packed));
} __packed;
struct uea_cmvs_v2 {
u32 group;
u32 address;
u32 offset;
u32 data;
} __attribute__ ((packed));
} __packed;
/* information about currently processed cmv */
struct cmv_dsc_e1 {
......@@ -352,7 +352,7 @@ struct block_index {
__le32 PageAddress;
__le16 dummy1;
__le16 PageNumber;
} __attribute__ ((packed));
} __packed;
#define E4_IS_BOOT_PAGE(PageSize) ((le32_to_cpu(PageSize)) & 0x80000000)
#define E4_PAGE_BYTES(PageSize) ((le32_to_cpu(PageSize) & 0x7fffffff) * 4)
......@@ -367,7 +367,7 @@ struct l1_code {
u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER];
struct block_index page_header[E4_NO_SWAPPAGE_HEADERS];
u8 code[0];
} __attribute__ ((packed));
} __packed;
/* structures describing a block within a DSP page */
struct block_info_e1 {
......@@ -377,7 +377,7 @@ struct block_info_e1 {
__le16 wOvlOffset;
__le16 wOvl; /* overlay */
__le16 wLast;
} __attribute__ ((packed));
} __packed;
#define E1_BLOCK_INFO_SIZE 12
struct block_info_e4 {
......@@ -387,7 +387,7 @@ struct block_info_e4 {
__be32 dwSize;
__be32 dwAddress;
__be16 wReserved;
} __attribute__ ((packed));
} __packed;
#define E4_BLOCK_INFO_SIZE 14
#define UEA_BIHDR 0xabcd
......@@ -467,7 +467,7 @@ struct cmv_e1 {
__le32 dwSymbolicAddress;
__le16 wOffsetAddress;
__le32 dwData;
} __attribute__ ((packed));
} __packed;
struct cmv_e4 {
__be16 wGroup;
......@@ -475,17 +475,17 @@ struct cmv_e4 {
__be16 wOffset;
__be16 wAddress;
__be32 dwData[6];
} __attribute__ ((packed));
} __packed;
/* structures representing swap information */
struct swap_info_e1 {
__u8 bSwapPageNo;
__u8 bOvl; /* overlay */
} __attribute__ ((packed));
} __packed;
struct swap_info_e4 {
__u8 bSwapPageNo;
} __attribute__ ((packed));
} __packed;
/* structures representing interrupt data */
#define e1_bSwapPageNo u.e1.s1.swapinfo.bSwapPageNo
......@@ -499,23 +499,23 @@ union intr_data_e1 {
struct {
struct swap_info_e1 swapinfo;
__le16 wDataSize;
} __attribute__ ((packed)) s1;
} __packed s1;
struct {
struct cmv_e1 cmv;
__le16 wDataSize;
} __attribute__ ((packed)) s2;
} __attribute__ ((packed));
} __packed s2;
} __packed;
union intr_data_e4 {
struct {
struct swap_info_e4 swapinfo;
__le16 wDataSize;
} __attribute__ ((packed)) s1;
} __packed s1;
struct {
struct cmv_e4 cmv;
__le16 wDataSize;
} __attribute__ ((packed)) s2;
} __attribute__ ((packed));
} __packed s2;
} __packed;
struct intr_pkt {
__u8 bType;
......@@ -528,15 +528,15 @@ struct intr_pkt {
union intr_data_e1 e1;
union intr_data_e4 e4;
} u;
} __attribute__ ((packed));
} __packed;
#define E1_INTR_PKT_SIZE 28
#define E4_INTR_PKT_SIZE 64
static struct usb_driver uea_driver;
static DEFINE_MUTEX(uea_mutex);
static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III",
"Eagle IV"};
static const char * const chip_name[] = {
"ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"};
static int modem_index;
static unsigned int debug;
......
......@@ -81,6 +81,7 @@
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/kthread.h>
#include <linux/ratelimit.h>
#ifdef VERBOSE_DEBUG
static int usbatm_print_packet(const unsigned char *data, int len);
......@@ -668,8 +669,7 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
/* racy disconnection check - fine */
if (!instance || instance->disconnected) {
#ifdef DEBUG
if (printk_ratelimit())
printk(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
printk_ratelimited(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance");
#endif
err = -ENODEV;
goto fail;
......
......@@ -58,6 +58,7 @@
#include <linux/mutex.h>
#undef DEBUG
#include <linux/usb.h>
#include <linux/ratelimit.h>
/*
* Version Information
......@@ -348,8 +349,7 @@ static int usblp_check_status(struct usblp *usblp, int err)
mutex_lock(&usblp->mut);
if ((error = usblp_read_status(usblp, usblp->statusbuf)) < 0) {
mutex_unlock(&usblp->mut);
if (printk_ratelimit())
printk(KERN_ERR
printk_ratelimited(KERN_ERR
"usblp%d: error %d reading printer status\n",
usblp->minor, error);
return 0;
......@@ -653,8 +653,7 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case LPGETSTATUS:
if ((retval = usblp_read_status(usblp, usblp->statusbuf))) {
if (printk_ratelimit())
printk(KERN_ERR "usblp%d:"
printk_ratelimited(KERN_ERR "usblp%d:"
"failed reading printer status (%d)\n",
usblp->minor, retval);
retval = -EIO;
......
......@@ -337,6 +337,17 @@ static const u8 ss_rh_config_descriptor[] = {
0x02, 0x00 /* __le16 ss_wBytesPerInterval; 15 bits for max 15 ports */
};
/* authorized_default behaviour:
* -1 is authorized for all devices except wireless (old behaviour)
* 0 is unauthorized for all devices
* 1 is authorized for all devices
*/
static int authorized_default = -1;
module_param(authorized_default, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(authorized_default,
"Default USB device authorization: 0 is not authorized, 1 is "
"authorized, -1 is authorized except for wireless USB (default, "
"old behaviour");
/*-------------------------------------------------------------------------*/
/**
......@@ -2371,7 +2382,11 @@ int usb_add_hcd(struct usb_hcd *hcd,
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
hcd->authorized_default = hcd->wireless? 0 : 1;
/* Keep old behaviour if authorized_default is not in [0, 1]. */
if (authorized_default < 0 || authorized_default > 1)
hcd->authorized_default = hcd->wireless? 0 : 1;
else
hcd->authorized_default = authorized_default;
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
/* HC is in reset state, but accessible. Now do the one-time init,
......
......@@ -96,9 +96,6 @@ config USB_GADGET_VBUS_DRAW
This value will be used except for system-specific gadget
drivers that have more specific information.
config USB_GADGET_SELECTED
boolean
#
# USB Peripheral Controller Support
#
......@@ -122,10 +119,9 @@ choice
# Integrated controllers
#
config USB_GADGET_AT91
boolean "Atmel AT91 USB Device Port"
config USB_AT91
tristate "Atmel AT91 USB Device Port"
depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 && !ARCH_AT91SAM9G45
select USB_GADGET_SELECTED
help
Many Atmel AT91 processors (such as the AT91RM2000) have a
full speed USB Device Port with support for five configurable
......@@ -135,27 +131,16 @@ config USB_GADGET_AT91
dynamically linked module called "at91_udc" and force all
gadget drivers to also be dynamically linked.
config USB_AT91
tristate
depends on USB_GADGET_AT91
default USB_GADGET
config USB_GADGET_ATMEL_USBA
boolean "Atmel USBA"
config USB_ATMEL_USBA
tristate "Atmel USBA"
select USB_GADGET_DUALSPEED
depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
help
USBA is the integrated high-speed USB Device controller on
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
config USB_ATMEL_USBA
tristate
depends on USB_GADGET_ATMEL_USBA
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_FSL_USB2
boolean "Freescale Highspeed USB DR Peripheral Controller"
config USB_FSL_USB2
tristate "Freescale Highspeed USB DR Peripheral Controller"
depends on FSL_SOC || ARCH_MXC
select USB_GADGET_DUALSPEED
select USB_FSL_MPH_DR_OF if OF
......@@ -170,26 +155,15 @@ config USB_GADGET_FSL_USB2
dynamically linked module called "fsl_usb2_udc" and force
all gadget drivers to also be dynamically linked.
config USB_FSL_USB2
tristate
depends on USB_GADGET_FSL_USB2
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_FUSB300
boolean "Faraday FUSB300 USB Peripheral Controller"
config USB_FUSB300
tristate "Faraday FUSB300 USB Peripheral Controller"
depends on !PHYS_ADDR_T_64BIT
select USB_GADGET_DUALSPEED
help
Faraday usb device controller FUSB300 driver
config USB_FUSB300
tristate
depends on USB_GADGET_FUSB300
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_OMAP
boolean "OMAP USB Device Controller"
config USB_OMAP
tristate "OMAP USB Device Controller"
depends on ARCH_OMAP
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
select USB_OTG_UTILS if ARCH_OMAP
......@@ -204,14 +178,8 @@ config USB_GADGET_OMAP
dynamically linked module called "omap_udc" and force all
gadget drivers to also be dynamically linked.
config USB_OMAP
tristate
depends on USB_GADGET_OMAP
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_PXA25X
boolean "PXA 25x or IXP 4xx"
config USB_PXA25X
tristate "PXA 25x or IXP 4xx"
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
select USB_OTG_UTILS
help
......@@ -226,24 +194,18 @@ config USB_GADGET_PXA25X
dynamically linked module called "pxa25x_udc" and force all
gadget drivers to also be dynamically linked.
config USB_PXA25X
tristate
depends on USB_GADGET_PXA25X
default USB_GADGET
select USB_GADGET_SELECTED
# if there's only one gadget driver, using only two bulk endpoints,
# don't waste memory for the other endpoints
config USB_PXA25X_SMALL
depends on USB_GADGET_PXA25X
depends on USB_PXA25X
bool
default n if USB_ETH_RNDIS
default y if USB_ZERO
default y if USB_ETH
default y if USB_G_SERIAL
config USB_GADGET_R8A66597
boolean "Renesas R8A66597 USB Peripheral Controller"
config USB_R8A66597
tristate "Renesas R8A66597 USB Peripheral Controller"
select USB_GADGET_DUALSPEED
help
R8A66597 is a discrete USB host and peripheral controller chip that
......@@ -254,32 +216,22 @@ config USB_GADGET_R8A66597
dynamically linked module called "r8a66597_udc" and force all
gadget drivers to also be dynamically linked.
config USB_R8A66597
tristate
depends on USB_GADGET_R8A66597
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_RENESAS_USBHS
boolean "Renesas USBHS"
config USB_RENESAS_USBHS_UDC
tristate 'Renesas USBHS controller'
depends on SUPERH || ARCH_SHMOBILE
depends on USB_RENESAS_USBHS
select USB_GADGET_DUALSPEED
help
Renesas USBHS is a discrete USB host and peripheral controller
chip that supports both full and high speed USB 2.0 data transfers.
platform is able to configure endpoint (pipe) style
Renesas USBHS is a discrete USB host and peripheral controller chip
that supports both full and high speed USB 2.0 data transfers.
It has nine or more configurable endpoints, and endpoint zero.
Say "y" to enable the gadget specific portion of the USBHS driver.
config USB_RENESAS_USBHS_UDC
tristate
depends on USB_GADGET_RENESAS_USBHS
default USB_GADGET
select USB_GADGET_SELECTED
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "renesas_usbhs" and force all
gadget drivers to also be dynamically linked.
config USB_GADGET_PXA27X
boolean "PXA 27x"
config USB_PXA27X
tristate "PXA 27x"
depends on ARCH_PXA && (PXA27x || PXA3xx)
select USB_OTG_UTILS
help
......@@ -293,14 +245,8 @@ config USB_GADGET_PXA27X
dynamically linked module called "pxa27x_udc" and force all
gadget drivers to also be dynamically linked.
config USB_PXA27X
tristate
depends on USB_GADGET_PXA27X
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_S3C_HSOTG
boolean "S3C HS/OtG USB Device controller"
config USB_S3C_HSOTG
tristate "S3C HS/OtG USB Device controller"
depends on S3C_DEV_USB_HSOTG
select USB_GADGET_S3C_HSOTG_PIO
select USB_GADGET_DUALSPEED
......@@ -308,14 +254,8 @@ config USB_GADGET_S3C_HSOTG
The Samsung S3C64XX USB2.0 high-speed gadget controller
integrated into the S3C64XX series SoC.
config USB_S3C_HSOTG
tristate
depends on USB_GADGET_S3C_HSOTG
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_IMX
boolean "Freescale IMX USB Peripheral Controller"
config USB_IMX
tristate "Freescale IMX USB Peripheral Controller"
depends on ARCH_MX1
help
Freescale's IMX series include an integrated full speed
......@@ -329,14 +269,8 @@ config USB_GADGET_IMX
dynamically linked module called "imx_udc" and force all
gadget drivers to also be dynamically linked.
config USB_IMX
tristate
depends on USB_GADGET_IMX
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_S3C2410
boolean "S3C2410 USB Device Controller"
config USB_S3C2410
tristate "S3C2410 USB Device Controller"
depends on ARCH_S3C2410
help
Samsung's S3C2410 is an ARM-4 processor with an integrated
......@@ -346,18 +280,12 @@ config USB_GADGET_S3C2410
This driver has been tested on the S3C2410, S3C2412, and
S3C2440 processors.
config USB_S3C2410
tristate
depends on USB_GADGET_S3C2410
default USB_GADGET
select USB_GADGET_SELECTED
config USB_S3C2410_DEBUG
boolean "S3C2410 udc debug messages"
depends on USB_GADGET_S3C2410
depends on USB_S3C2410
config USB_GADGET_S3C_HSUDC
boolean "S3C2416, S3C2443 and S3C2450 USB Device Controller"
config USB_S3C_HSUDC
tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
depends on ARCH_S3C2410
select USB_GADGET_DUALSPEED
help
......@@ -367,41 +295,29 @@ config USB_GADGET_S3C_HSUDC
This driver has been tested on S3C2416 and S3C2450 processors.
config USB_S3C_HSUDC
tristate
depends on USB_GADGET_S3C_HSUDC
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_PXA_U2O
boolean "PXA9xx Processor USB2.0 controller"
config USB_PXA_U2O
tristate "PXA9xx Processor USB2.0 controller"
depends on ARCH_MMP
select USB_GADGET_DUALSPEED
help
PXA9xx Processor series include a high speed USB2.0 device
controller, which support high speed and full speed USB peripheral.
config USB_PXA_U2O
tristate
depends on USB_GADGET_PXA_U2O
default USB_GADGET
select USB_GADGET_SELECTED
#
# Controllers available in both integrated and discrete versions
#
# musb builds in ../musb along with host support
config USB_GADGET_MUSB_HDRC
boolean "Inventra HDRC USB Peripheral (TI, ADI, ...)"
tristate "Inventra HDRC USB Peripheral (TI, ADI, ...)"
depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG)
select USB_GADGET_DUALSPEED
select USB_GADGET_SELECTED
help
This OTG-capable silicon IP is used in dual designs including
the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
config USB_GADGET_M66592
boolean "Renesas M66592 USB Peripheral Controller"
config USB_M66592
tristate "Renesas M66592 USB Peripheral Controller"
select USB_GADGET_DUALSPEED
help
M66592 is a discrete USB peripheral controller chip that
......@@ -412,18 +328,12 @@ config USB_GADGET_M66592
dynamically linked module called "m66592_udc" and force all
gadget drivers to also be dynamically linked.
config USB_M66592
tristate
depends on USB_GADGET_M66592
default USB_GADGET
select USB_GADGET_SELECTED
#
# Controllers available only in discrete form (and all PCI controllers)
#
config USB_GADGET_AMD5536UDC
boolean "AMD5536 UDC"
config USB_AMD5536UDC
tristate "AMD5536 UDC"
depends on PCI
select USB_GADGET_DUALSPEED
help
......@@ -437,14 +347,8 @@ config USB_GADGET_AMD5536UDC
dynamically linked module called "amd5536udc" and force all
gadget drivers to also be dynamically linked.
config USB_AMD5536UDC
tristate
depends on USB_GADGET_AMD5536UDC
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_FSL_QE
boolean "Freescale QE/CPM USB Device Controller"
config USB_FSL_QE
tristate "Freescale QE/CPM USB Device Controller"
depends on FSL_SOC && (QUICC_ENGINE || CPM)
help
Some of Freescale PowerPC processors have a Full Speed
......@@ -456,14 +360,8 @@ config USB_GADGET_FSL_QE
Set CONFIG_USB_GADGET to "m" to build this driver as a
dynamically linked module called "fsl_qe_udc".
config USB_FSL_QE
tristate
depends on USB_GADGET_FSL_QE
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_CI13XXX_PCI
boolean "MIPS USB CI13xxx PCI UDC"
config USB_CI13XXX_PCI
tristate "MIPS USB CI13xxx PCI UDC"
depends on PCI
select USB_GADGET_DUALSPEED
help
......@@ -474,14 +372,31 @@ config USB_GADGET_CI13XXX_PCI
dynamically linked module called "ci13xxx_udc" and force all
gadget drivers to also be dynamically linked.
config USB_CI13XXX_PCI
tristate
depends on USB_GADGET_CI13XXX_PCI
default USB_GADGET
select USB_GADGET_SELECTED
config USB_NET2272
tristate "PLX NET2272"
select USB_GADGET_DUALSPEED
help
PLX NET2272 is a USB peripheral controller which supports
both full and high speed USB 2.0 data transfers.
It has three configurable endpoints, as well as endpoint zero
(for control transfer).
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "net2272" and force all
gadget drivers to also be dynamically linked.
config USB_NET2272_DMA
boolean "Support external DMA controller"
depends on USB_NET2272
help
The NET2272 part can optionally support an external DMA
controller, but your board has to have support in the
driver itself.
config USB_GADGET_NET2280
boolean "NetChip 228x"
If unsure, say "N" here. The driver works fine in PIO mode.
config USB_NET2280
tristate "NetChip 228x"
depends on PCI
select USB_GADGET_DUALSPEED
help
......@@ -496,14 +411,8 @@ config USB_GADGET_NET2280
dynamically linked module called "net2280" and force all
gadget drivers to also be dynamically linked.
config USB_NET2280
tristate
depends on USB_GADGET_NET2280
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_GOKU
boolean "Toshiba TC86C001 'Goku-S'"
config USB_GOKU
tristate "Toshiba TC86C001 'Goku-S'"
depends on PCI
help
The Toshiba TC86C001 is a PCI device which includes controllers
......@@ -516,15 +425,10 @@ config USB_GADGET_GOKU
dynamically linked module called "goku_udc" and to force all
gadget drivers to also be dynamically linked.
config USB_GOKU
tristate
depends on USB_GADGET_GOKU
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_LANGWELL
boolean "Intel Langwell USB Device Controller"
config USB_LANGWELL
tristate "Intel Langwell USB Device Controller"
depends on PCI
depends on !PHYS_ADDR_T_64BIT
select USB_GADGET_DUALSPEED
help
Intel Langwell USB Device Controller is a High-Speed USB
......@@ -537,14 +441,8 @@ config USB_GADGET_LANGWELL
dynamically linked module called "langwell_udc" and force all
gadget drivers to also be dynamically linked.
config USB_LANGWELL
tristate
depends on USB_GADGET_LANGWELL
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_EG20T
boolean "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
config USB_EG20T
tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
depends on PCI
select USB_GADGET_DUALSPEED
help
......@@ -565,14 +463,8 @@ config USB_GADGET_EG20T
ML7213 is companion chip for Intel Atom E6xx series.
ML7213 is completely compatible for Intel EG20T PCH.
config USB_EG20T
tristate
depends on USB_GADGET_EG20T
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_CI13XXX_MSM
boolean "MIPS USB CI13xxx for MSM"
config USB_CI13XXX_MSM
tristate "MIPS USB CI13xxx for MSM"
depends on ARCH_MSM
select USB_GADGET_DUALSPEED
select USB_MSM_OTG
......@@ -588,31 +480,26 @@ config USB_GADGET_CI13XXX_MSM
dynamically linked module called "ci13xxx_msm" and force all
gadget drivers to also be dynamically linked.
config USB_CI13XXX_MSM
tristate
depends on USB_GADGET_CI13XXX_MSM
default USB_GADGET
select USB_GADGET_SELECTED
#
# LAST -- dummy/emulated controller
#
config USB_GADGET_DUMMY_HCD
boolean "Dummy HCD (DEVELOPMENT)"
config USB_DUMMY_HCD
tristate "Dummy HCD (DEVELOPMENT)"
depends on USB=y || (USB=m && USB_GADGET=m)
select USB_GADGET_DUALSPEED
select USB_GADGET_SUPERSPEED
help
This host controller driver emulates USB, looping all data transfer
requests back to a USB "gadget driver" in the same host. The host
side is the master; the gadget side is the slave. Gadget drivers
can be high, full, or low speed; and they have access to endpoints
like those from NET2280, PXA2xx, or SA1100 hardware.
This may help in some stages of creating a driver to embed in a
Linux device, since it lets you debug several parts of the gadget
driver without its hardware or drivers being involved.
Since such a gadget side driver needs to interoperate with a host
side Linux-USB device driver, this may help to debug both sides
of a USB protocol stack.
......@@ -621,12 +508,6 @@ config USB_GADGET_DUMMY_HCD
dynamically linked module called "dummy_hcd" and force all
gadget drivers to also be dynamically linked.
config USB_DUMMY_HCD
tristate
depends on USB_GADGET_DUMMY_HCD
default USB_GADGET
select USB_GADGET_SELECTED
# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears
# first and will be selected by default.
......@@ -637,12 +518,18 @@ config USB_GADGET_DUALSPEED
bool
depends on USB_GADGET
# Selected by UDC drivers that support super-speed opperation
config USB_GADGET_SUPERSPEED
bool
depends on USB_GADGET
depends on USB_GADGET_DUALSPEED
#
# USB Gadget Drivers
#
choice
tristate "USB Gadget Drivers"
depends on USB_GADGET && USB_GADGET_SELECTED
depends on USB_GADGET
default USB_ETH
help
A Linux "Gadget Driver" talks to the USB Peripheral Controller
......@@ -848,7 +735,7 @@ config USB_FUNCTIONFS_GENERIC
no Ethernet interface.
config USB_FILE_STORAGE
tristate "File-backed Storage Gadget"
tristate "File-backed Storage Gadget (DEPRECATED)"
depends on BLOCK
help
The File-backed Storage Gadget acts as a USB Mass Storage
......@@ -859,6 +746,9 @@ config USB_FILE_STORAGE
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
......@@ -878,14 +768,11 @@ config USB_MASS_STORAGE
device (in much the same way as the "loop" device driver),
specified as a module parameter or sysfs option.
This is heavily based on File-backed Storage Gadget and in most
cases you will want to use FSG instead. This gadget is mostly
here to test the functionality of the Mass Storage Function
which may be used with composite framework.
This driver is an updated replacement for the deprecated
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". If unsure,
consider File-backed Storage Gadget.
a dynamically linked module called "g_mass_storage".
config USB_G_SERIAL
tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
......
......@@ -3,7 +3,9 @@
#
ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_GADGET) += udc-core.o
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2272) += net2272.o
obj-$(CONFIG_USB_NET2280) += net2280.o
obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o
obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o
......
......@@ -1438,10 +1438,15 @@ static int udc_wakeup(struct usb_gadget *gadget)
return 0;
}
static int amd5536_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int amd5536_stop(struct usb_gadget_driver *driver);
/* gadget operations */
static const struct usb_gadget_ops udc_ops = {
.wakeup = udc_wakeup,
.get_frame = udc_get_frame,
.start = amd5536_start,
.stop = amd5536_stop,
};
/* Setups endpoint parameters, adds endpoints to linked list */
......@@ -1955,7 +1960,7 @@ static int setup_ep0(struct udc *dev)
}
/* Called by gadget driver to register itself */
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int amd5536_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct udc *dev = udc;
......@@ -2002,7 +2007,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
return 0;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
/* shutdown requests and disconnect from gadget */
static void
......@@ -2027,7 +2031,7 @@ __acquires(dev->lock)
}
/* Called by gadget driver to unregister itself */
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int amd5536_stop(struct usb_gadget_driver *driver)
{
struct udc *dev = udc;
unsigned long flags;
......@@ -2057,8 +2061,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/* Clear pending NAK bits */
static void udc_process_cnak_queue(struct udc *dev)
......@@ -3134,6 +3136,7 @@ static void udc_pci_remove(struct pci_dev *pdev)
dev = pci_get_drvdata(pdev);
usb_del_gadget_udc(&udc->gadget);
/* gadget driver must not be registered */
BUG_ON(dev->driver != NULL);
......@@ -3382,8 +3385,13 @@ static int udc_probe(struct udc *dev)
"driver version: %s(for Geode5536 B1)\n", tmp);
udc = dev;
retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget);
if (retval)
goto finished;
retval = device_register(&dev->gadget.dev);
if (retval) {
usb_del_gadget_udc(&dev->gadget);
put_device(&dev->gadget.dev);
goto finished;
}
......
......@@ -985,12 +985,18 @@ static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
return 0;
}
static int at91_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int at91_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops at91_udc_ops = {
.get_frame = at91_get_frame,
.wakeup = at91_wakeup,
.set_selfpowered = at91_set_selfpowered,
.vbus_session = at91_vbus_session,
.pullup = at91_pullup,
.start = at91_start,
.stop = at91_stop,
/*
* VBUS-powered devices may also also want to support bigger
......@@ -1628,7 +1634,7 @@ static void at91_vbus_timer(unsigned long data)
schedule_work(&udc->vbus_timer_work);
}
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int at91_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct at91_udc *udc = &controller;
......@@ -1672,9 +1678,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
DBG("bound to %s\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
static int at91_stop(struct usb_gadget_driver *driver)
{
struct at91_udc *udc = &controller;
unsigned long flags;
......@@ -1696,7 +1701,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
DBG("unbound from %s\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL (usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------*/
......@@ -1854,13 +1858,18 @@ static int __init at91udc_probe(struct platform_device *pdev)
DBG("no VBUS detection, assuming always-on\n");
udc->vbus = 1;
}
retval = usb_add_gadget_udc(dev, &udc->gadget);
if (retval)
goto fail4;
dev_set_drvdata(dev, udc);
device_init_wakeup(dev, 1);
create_debug_file(udc);
INFO("%s version %s\n", driver_name, DRIVER_VERSION);
return 0;
fail4:
if (udc->board.vbus_pin > 0 && !udc->board.vbus_polled)
free_irq(udc->board.vbus_pin, udc);
fail3:
if (udc->board.vbus_pin > 0)
gpio_free(udc->board.vbus_pin);
......@@ -1887,6 +1896,7 @@ static int __exit at91udc_remove(struct platform_device *pdev)
DBG("remove\n");
usb_del_gadget_udc(&udc->gadget);
if (udc->driver)
return -EBUSY;
......
......@@ -1007,10 +1007,16 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered)
return 0;
}
static int atmel_usba_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int atmel_usba_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops usba_udc_ops = {
.get_frame = usba_udc_get_frame,
.wakeup = usba_udc_wakeup,
.set_selfpowered = usba_udc_set_selfpowered,
.start = atmel_usba_start,
.stop = atmel_usba_stop,
};
static struct usb_endpoint_descriptor usba_ep0_desc = {
......@@ -1789,7 +1795,7 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid)
return IRQ_HANDLED;
}
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int atmel_usba_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct usba_udc *udc = &the_udc;
......@@ -1842,9 +1848,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
udc->gadget.dev.driver = NULL;
return ret;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int atmel_usba_stop(struct usb_gadget_driver *driver)
{
struct usba_udc *udc = &the_udc;
unsigned long flags;
......@@ -1880,7 +1885,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
static int __init usba_udc_probe(struct platform_device *pdev)
{
......@@ -2021,12 +2025,24 @@ static int __init usba_udc_probe(struct platform_device *pdev)
}
}
ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (ret)
goto err_add_udc;
usba_init_debugfs(udc);
for (i = 1; i < pdata->num_ep; i++)
usba_ep_init_debugfs(udc, &usba_ep[i]);
return 0;
err_add_udc:
if (gpio_is_valid(pdata->vbus_pin)) {
free_irq(gpio_to_irq(udc->vbus_pin), udc);
gpio_free(udc->vbus_pin);
}
device_unregister(&udc->gadget.dev);
err_device_add:
free_irq(irq, udc);
err_request_irq:
......@@ -2053,6 +2069,8 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
udc = platform_get_drvdata(pdev);
usb_del_gadget_udc(&udc->gadget);
for (i = 1; i < pdata->num_ep; i++)
usba_ep_cleanup_debugfs(&usba_ep[i]);
usba_cleanup_debugfs(udc);
......
......@@ -165,6 +165,7 @@ static struct usb_composite_driver audio_driver = {
.name = "g_audio",
.dev = &device_desc,
.strings = audio_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = __exit_p(audio_unbind),
};
......
......@@ -244,6 +244,7 @@ static struct usb_composite_driver cdc_driver = {
.name = "g_cdc",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = __exit_p(cdc_unbind),
};
......
......@@ -126,6 +126,7 @@ static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
.driver = { .name = "msm_hsusb", },
};
MODULE_ALIAS("platform:msm_hsusb");
static int __init ci13xxx_msm_init(void)
{
......
......@@ -857,7 +857,7 @@ static void dbg_print(u8 addr, const char *name, int status, const char *extra)
stamp = stamp * 1000000 + tval.tv_usec;
scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
"%04X\t %02X %-7.7s %4i \t%s\n",
"%04X\t? %02X %-7.7s %4i ?\t%s\n",
stamp, addr, name, status, extra);
dbg_inc(&dbg_data.idx);
......@@ -865,7 +865,7 @@ static void dbg_print(u8 addr, const char *name, int status, const char *extra)
write_unlock_irqrestore(&dbg_data.lck, flags);
if (dbg_data.tty != 0)
pr_notice("%04X\t %02X %-7.7s %4i \t%s\n",
pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
stamp, addr, name, status, extra);
}
......@@ -1025,15 +1025,15 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
isr_statistics.test);
n += scnprintf(buf + n, PAGE_SIZE - n, " ui = %d\n",
n += scnprintf(buf + n, PAGE_SIZE - n, "? ui = %d\n",
isr_statistics.ui);
n += scnprintf(buf + n, PAGE_SIZE - n, " uei = %d\n",
n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
isr_statistics.uei);
n += scnprintf(buf + n, PAGE_SIZE - n, " pci = %d\n",
n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
isr_statistics.pci);
n += scnprintf(buf + n, PAGE_SIZE - n, " uri = %d\n",
n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
isr_statistics.uri);
n += scnprintf(buf + n, PAGE_SIZE - n, " sli = %d\n",
n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
isr_statistics.sli);
n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
isr_statistics.none);
......@@ -1214,12 +1214,13 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
*
* Check "device.h" for details
*/
#define DUMP_ENTRIES 512
static ssize_t show_registers(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
u32 dump[512];
u32 *dump;
unsigned i, k, n = 0;
dbg_trace("[%s] %p\n", __func__, buf);
......@@ -1228,8 +1229,14 @@ static ssize_t show_registers(struct device *dev,
return 0;
}
dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
if (!dump) {
dev_err(dev, "%s: out of memory\n", __func__);
return 0;
}
spin_lock_irqsave(udc->lock, flags);
k = hw_register_read(dump, sizeof(dump)/sizeof(u32));
k = hw_register_read(dump, DUMP_ENTRIES);
spin_unlock_irqrestore(udc->lock, flags);
for (i = 0; i < k; i++) {
......@@ -1237,6 +1244,7 @@ static ssize_t show_registers(struct device *dev,
"reg[0x%04X] = 0x%08X\n",
i * (unsigned)sizeof(u32), dump[i]);
}
kfree(dump);
return n;
}
......@@ -2515,6 +2523,9 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
return -ENOTSUPP;
}
static int ci13xxx_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int ci13xxx_stop(struct usb_gadget_driver *driver);
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
......@@ -2524,17 +2535,19 @@ static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup,
.vbus_draw = ci13xxx_vbus_draw,
.start = ci13xxx_start,
.stop = ci13xxx_stop,
};
/**
* usb_gadget_probe_driver: register a gadget driver
* ci13xxx_start: register a gadget driver
* @driver: the driver being registered
* @bind: the driver's bind callback
*
* Check usb_gadget_probe_driver() at <linux/usb/gadget.h> for details.
* Check ci13xxx_start() at <linux/usb/gadget.h> for details.
* Interrupts are enabled here.
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int ci13xxx_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct ci13xxx *udc = _udc;
......@@ -2615,10 +2628,13 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
if (retval)
goto done;
spin_unlock_irqrestore(udc->lock, flags);
retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc);
udc->ep0out.ep.desc = &ctrl_endpt_out_desc;
retval = usb_ep_enable(&udc->ep0out.ep);
if (retval)
return retval;
retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc);
udc->ep0in.ep.desc = &ctrl_endpt_in_desc;
retval = usb_ep_enable(&udc->ep0in.ep);
if (retval)
return retval;
spin_lock_irqsave(udc->lock, flags);
......@@ -2657,14 +2673,13 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
spin_unlock_irqrestore(udc->lock, flags);
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
/**
* usb_gadget_unregister_driver: unregister a gadget driver
* ci13xxx_stop: unregister a gadget driver
*
* Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
*/
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int ci13xxx_stop(struct usb_gadget_driver *driver)
{
struct ci13xxx *udc = _udc;
unsigned long i, flags;
......@@ -2726,7 +2741,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/******************************************************************************
* BUS block
......@@ -2901,12 +2915,23 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
if (retval)
goto remove_dbg;
}
retval = usb_add_gadget_udc(dev, &udc->gadget);
if (retval)
goto remove_trans;
pm_runtime_no_callbacks(&udc->gadget.dev);
pm_runtime_enable(&udc->gadget.dev);
_udc = udc;
return retval;
remove_trans:
if (udc->transceiver) {
otg_set_peripheral(udc->transceiver, &udc->gadget);
otg_put_transceiver(udc->transceiver);
}
err("error = %i", retval);
remove_dbg:
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
......@@ -2936,6 +2961,7 @@ static void udc_remove(void)
err("EINVAL");
return;
}
usb_del_gadget_udc(&udc->gadget);
if (udc->transceiver) {
otg_set_peripheral(udc->transceiver, &udc->gadget);
......
......@@ -27,7 +27,7 @@
#include <linux/utsname.h>
#include <linux/usb/composite.h>
#include <asm/unaligned.h>
/*
* The code in this file is utility code, used to build a gadget driver
......@@ -74,6 +74,130 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
static char composite_manufacturer[50];
/*-------------------------------------------------------------------------*/
/**
* next_ep_desc() - advance to the next EP descriptor
* @t: currect pointer within descriptor array
*
* Return: next EP descriptor or NULL
*
* Iterate over @t until either EP descriptor found or
* NULL (that indicates end of list) encountered
*/
static struct usb_descriptor_header**
next_ep_desc(struct usb_descriptor_header **t)
{
for (; *t; t++) {
if ((*t)->bDescriptorType == USB_DT_ENDPOINT)
return t;
}
return NULL;
}
/*
* for_each_ep_desc()- iterate over endpoint descriptors in the
* descriptors list
* @start: pointer within descriptor array.
* @ep_desc: endpoint descriptor to use as the loop cursor
*/
#define for_each_ep_desc(start, ep_desc) \
for (ep_desc = next_ep_desc(start); \
ep_desc; ep_desc = next_ep_desc(ep_desc+1))
/**
* config_ep_by_speed() - configures the given endpoint
* according to gadget speed.
* @g: pointer to the gadget
* @f: usb function
* @_ep: the endpoint to configure
*
* Return: error code, 0 on success
*
* This function chooses the right descriptors for a given
* endpoint according to gadget speed and saves it in the
* endpoint desc field. If the endpoint already has a descriptor
* assigned to it - overwrites it with currently corresponding
* descriptor. The endpoint maxpacket field is updated according
* to the chosen descriptor.
* Note: the supplied function should hold all the descriptors
* for supported speeds
*/
int config_ep_by_speed(struct usb_gadget *g,
struct usb_function *f,
struct usb_ep *_ep)
{
struct usb_endpoint_descriptor *chosen_desc = NULL;
struct usb_descriptor_header **speed_desc = NULL;
struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
int want_comp_desc = 0;
struct usb_descriptor_header **d_spd; /* cursor for speed desc */
if (!g || !f || !_ep)
return -EIO;
/* select desired speed */
switch (g->speed) {
case USB_SPEED_SUPER:
if (gadget_is_superspeed(g)) {
speed_desc = f->ss_descriptors;
want_comp_desc = 1;
break;
}
/* else: Fall trough */
case USB_SPEED_HIGH:
if (gadget_is_dualspeed(g)) {
speed_desc = f->hs_descriptors;
break;
}
/* else: fall through */
default:
speed_desc = f->descriptors;
}
/* find descriptors */
for_each_ep_desc(speed_desc, d_spd) {
chosen_desc = (struct usb_endpoint_descriptor *)*d_spd;
if (chosen_desc->bEndpointAddress == _ep->address)
goto ep_found;
}
return -EIO;
ep_found:
/* commit results */
_ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize);
_ep->desc = chosen_desc;
_ep->comp_desc = NULL;
_ep->maxburst = 0;
_ep->mult = 0;
if (!want_comp_desc)
return 0;
/*
* Companion descriptor should follow EP descriptor
* USB 3.0 spec, #9.6.7
*/
comp_desc = (struct usb_ss_ep_comp_descriptor *)*(++d_spd);
if (!comp_desc ||
(comp_desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP))
return -EIO;
_ep->comp_desc = comp_desc;
if (g->speed == USB_SPEED_SUPER) {
switch (usb_endpoint_type(_ep->desc)) {
case USB_ENDPOINT_XFER_BULK:
case USB_ENDPOINT_XFER_INT:
_ep->maxburst = comp_desc->bMaxBurst;
break;
case USB_ENDPOINT_XFER_ISOC:
/* mult: bits 1:0 of bmAttributes */
_ep->mult = comp_desc->bmAttributes & 0x3;
break;
default:
/* Do nothing for control endpoints */
break;
}
}
return 0;
}
/**
* usb_add_function() - add a function to a configuration
......@@ -123,6 +247,8 @@ int usb_add_function(struct usb_configuration *config,
config->fullspeed = true;
if (!config->highspeed && function->hs_descriptors)
config->highspeed = true;
if (!config->superspeed && function->ss_descriptors)
config->superspeed = true;
done:
if (value)
......@@ -266,10 +392,17 @@ static int config_buf(struct usb_configuration *config,
list_for_each_entry(f, &config->functions, list) {
struct usb_descriptor_header **descriptors;
if (speed == USB_SPEED_HIGH)
switch (speed) {
case USB_SPEED_SUPER:
descriptors = f->ss_descriptors;
break;
case USB_SPEED_HIGH:
descriptors = f->hs_descriptors;
else
break;
default:
descriptors = f->descriptors;
}
if (!descriptors)
continue;
status = usb_descriptor_fillbuf(next, len,
......@@ -292,9 +425,10 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
u8 type = w_value >> 8;
enum usb_device_speed speed = USB_SPEED_UNKNOWN;
if (gadget_is_dualspeed(gadget)) {
int hs = 0;
if (gadget->speed == USB_SPEED_SUPER)
speed = gadget->speed;
else if (gadget_is_dualspeed(gadget)) {
int hs = 0;
if (gadget->speed == USB_SPEED_HIGH)
hs = 1;
if (type == USB_DT_OTHER_SPEED_CONFIG)
......@@ -308,13 +442,20 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
w_value &= 0xff;
list_for_each_entry(c, &cdev->configs, list) {
/* ignore configs that won't work at this speed */
if (speed == USB_SPEED_HIGH) {
switch (speed) {
case USB_SPEED_SUPER:
if (!c->superspeed)
continue;
break;
case USB_SPEED_HIGH:
if (!c->highspeed)
continue;
} else {
break;
default:
if (!c->fullspeed)
continue;
}
if (w_value == 0)
return config_buf(c, speed, cdev->req->buf, type);
w_value--;
......@@ -328,16 +469,22 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
struct usb_configuration *c;
unsigned count = 0;
int hs = 0;
int ss = 0;
if (gadget_is_dualspeed(gadget)) {
if (gadget->speed == USB_SPEED_HIGH)
hs = 1;
if (gadget->speed == USB_SPEED_SUPER)
ss = 1;
if (type == USB_DT_DEVICE_QUALIFIER)
hs = !hs;
}
list_for_each_entry(c, &cdev->configs, list) {
/* ignore configs that won't work at this speed */
if (hs) {
if (ss) {
if (!c->superspeed)
continue;
} else if (hs) {
if (!c->highspeed)
continue;
} else {
......@@ -349,6 +496,71 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
return count;
}
/**
* bos_desc() - prepares the BOS descriptor.
* @cdev: pointer to usb_composite device to generate the bos
* descriptor for
*
* This function generates the BOS (Binary Device Object)
* descriptor and its device capabilities descriptors. The BOS
* descriptor should be supported by a SuperSpeed device.
*/
static int bos_desc(struct usb_composite_dev *cdev)
{
struct usb_ext_cap_descriptor *usb_ext;
struct usb_ss_cap_descriptor *ss_cap;
struct usb_dcd_config_params dcd_config_params;
struct usb_bos_descriptor *bos = cdev->req->buf;
bos->bLength = USB_DT_BOS_SIZE;
bos->bDescriptorType = USB_DT_BOS;
bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE);
bos->bNumDeviceCaps = 0;
/*
* A SuperSpeed device shall include the USB2.0 extension descriptor
* and shall support LPM when operating in USB2.0 HS mode.
*/
usb_ext = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
bos->bNumDeviceCaps++;
le16_add_cpu(&bos->wTotalLength, USB_DT_USB_EXT_CAP_SIZE);
usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
/*
* The Superspeed USB Capability descriptor shall be implemented by all
* SuperSpeed devices.
*/
ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
bos->bNumDeviceCaps++;
le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
ss_cap->bmAttributes = 0; /* LTM is not supported yet */
ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
USB_FULL_SPEED_OPERATION |
USB_HIGH_SPEED_OPERATION |
USB_5GBPS_OPERATION);
ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
/* Get Controller configuration */
if (cdev->gadget->ops->get_config_params)
cdev->gadget->ops->get_config_params(&dcd_config_params);
else {
dcd_config_params.bU1devExitLat = USB_DEFULT_U1_DEV_EXIT_LAT;
dcd_config_params.bU2DevExitLat =
cpu_to_le16(USB_DEFULT_U2_DEV_EXIT_LAT);
}
ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
return le16_to_cpu(bos->wTotalLength);
}
static void device_qual(struct usb_composite_dev *cdev)
{
struct usb_qualifier_descriptor *qual = cdev->req->buf;
......@@ -361,7 +573,7 @@ static void device_qual(struct usb_composite_dev *cdev)
qual->bDeviceSubClass = cdev->desc.bDeviceSubClass;
qual->bDeviceProtocol = cdev->desc.bDeviceProtocol;
/* ASSUME same EP0 fifo size at both speeds */
qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0;
qual->bMaxPacketSize0 = cdev->gadget->ep0->maxpacket;
qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER);
qual->bRESERVED = 0;
}
......@@ -392,28 +604,46 @@ static int set_config(struct usb_composite_dev *cdev,
unsigned power = gadget_is_otg(gadget) ? 8 : 100;
int tmp;
if (cdev->config)
reset_config(cdev);
if (number) {
list_for_each_entry(c, &cdev->configs, list) {
if (c->bConfigurationValue == number) {
/*
* We disable the FDs of the previous
* configuration only if the new configuration
* is a valid one
*/
if (cdev->config)
reset_config(cdev);
result = 0;
break;
}
}
if (result < 0)
goto done;
} else
} else { /* Zero configuration value - need to reset the config */
if (cdev->config)
reset_config(cdev);
result = 0;
}
INFO(cdev, "%s speed config #%d: %s\n",
({ char *speed;
switch (gadget->speed) {
case USB_SPEED_LOW: speed = "low"; break;
case USB_SPEED_FULL: speed = "full"; break;
case USB_SPEED_HIGH: speed = "high"; break;
default: speed = "?"; break;
case USB_SPEED_LOW:
speed = "low";
break;
case USB_SPEED_FULL:
speed = "full";
break;
case USB_SPEED_HIGH:
speed = "high";
break;
case USB_SPEED_SUPER:
speed = "super";
break;
default:
speed = "?";
break;
} ; speed; }), number, c ? c->label : "unconfigured");
if (!c)
......@@ -435,10 +665,16 @@ static int set_config(struct usb_composite_dev *cdev,
* function's setup callback instead of the current
* configuration's setup callback.
*/
if (gadget->speed == USB_SPEED_HIGH)
switch (gadget->speed) {
case USB_SPEED_SUPER:
descriptors = f->ss_descriptors;
break;
case USB_SPEED_HIGH:
descriptors = f->hs_descriptors;
else
break;
default:
descriptors = f->descriptors;
}
for (; *descriptors; ++descriptors) {
struct usb_endpoint_descriptor *ep;
......@@ -531,8 +767,9 @@ int usb_add_config(struct usb_composite_dev *cdev,
} else {
unsigned i;
DBG(cdev, "cfg %d/%p speeds:%s%s\n",
DBG(cdev, "cfg %d/%p speeds:%s%s%s\n",
config->bConfigurationValue, config,
config->superspeed ? " super" : "",
config->highspeed ? " high" : "",
config->fullspeed
? (gadget_is_dualspeed(cdev->gadget)
......@@ -811,6 +1048,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct usb_composite_dev *cdev = get_gadget_data(gadget);
struct usb_request *req = cdev->req;
int value = -EOPNOTSUPP;
int status = 0;
u16 w_index = le16_to_cpu(ctrl->wIndex);
u8 intf = w_index & 0xFF;
u16 w_value = le16_to_cpu(ctrl->wValue);
......@@ -838,18 +1076,29 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_DT_DEVICE:
cdev->desc.bNumConfigurations =
count_configs(cdev, USB_DT_DEVICE);
cdev->desc.bMaxPacketSize0 =
cdev->gadget->ep0->maxpacket;
if (gadget_is_superspeed(gadget)) {
if (gadget->speed >= USB_SPEED_SUPER)
cdev->desc.bcdUSB = cpu_to_le16(0x0300);
else
cdev->desc.bcdUSB = cpu_to_le16(0x0210);
}
value = min(w_length, (u16) sizeof cdev->desc);
memcpy(req->buf, &cdev->desc, value);
break;
case USB_DT_DEVICE_QUALIFIER:
if (!gadget_is_dualspeed(gadget))
if (!gadget_is_dualspeed(gadget) ||
gadget->speed >= USB_SPEED_SUPER)
break;
device_qual(cdev);
value = min_t(int, w_length,
sizeof(struct usb_qualifier_descriptor));
break;
case USB_DT_OTHER_SPEED_CONFIG:
if (!gadget_is_dualspeed(gadget))
if (!gadget_is_dualspeed(gadget) ||
gadget->speed >= USB_SPEED_SUPER)
break;
/* FALLTHROUGH */
case USB_DT_CONFIG:
......@@ -863,6 +1112,12 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (value >= 0)
value = min(w_length, (u16) value);
break;
case USB_DT_BOS:
if (gadget_is_superspeed(gadget)) {
value = bos_desc(cdev);
value = min(w_length, (u16) value);
}
break;
}
break;
......@@ -930,6 +1185,61 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
*((u8 *)req->buf) = value;
value = min(w_length, (u16) 1);
break;
/*
* USB 3.0 additions:
* Function driver should handle get_status request. If such cb
* wasn't supplied we respond with default value = 0
* Note: function driver should supply such cb only for the first
* interface of the function
*/
case USB_REQ_GET_STATUS:
if (!gadget_is_superspeed(gadget))
goto unknown;
if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE))
goto unknown;
value = 2; /* This is the length of the get_status reply */
put_unaligned_le16(0, req->buf);
if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
break;
f = cdev->config->interface[intf];
if (!f)
break;
status = f->get_status ? f->get_status(f) : 0;
if (status < 0)
break;
put_unaligned_le16(status & 0x0000ffff, req->buf);
break;
/*
* Function drivers should handle SetFeature/ClearFeature
* (FUNCTION_SUSPEND) request. function_suspend cb should be supplied
* only for the first interface of the function
*/
case USB_REQ_CLEAR_FEATURE:
case USB_REQ_SET_FEATURE:
if (!gadget_is_superspeed(gadget))
goto unknown;
if (ctrl->bRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE))
goto unknown;
switch (w_value) {
case USB_INTRF_FUNC_SUSPEND:
if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
break;
f = cdev->config->interface[intf];
if (!f)
break;
value = 0;
if (f->func_suspend)
value = f->func_suspend(f, w_index >> 8);
if (value < 0) {
ERROR(cdev,
"func_suspend() returned error %d\n",
value);
value = 0;
}
break;
}
break;
default:
unknown:
VDBG(cdev,
......@@ -1140,7 +1450,6 @@ static int composite_bind(struct usb_gadget *gadget)
goto fail;
cdev->desc = *composite->dev;
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
/* standardized runtime overrides for device ID data */
if (idVendor)
......@@ -1247,7 +1556,11 @@ composite_resume(struct usb_gadget *gadget)
/*-------------------------------------------------------------------------*/
static struct usb_gadget_driver composite_driver = {
#ifdef CONFIG_USB_GADGET_SUPERSPEED
.speed = USB_SPEED_SUPER,
#else
.speed = USB_SPEED_HIGH,
#endif
.unbind = composite_unbind,
......@@ -1293,6 +1606,8 @@ int usb_composite_probe(struct usb_composite_driver *driver,
driver->iProduct = driver->name;
composite_driver.function = (char *) driver->name;
composite_driver.driver.name = driver->name;
composite_driver.speed = min((u8)composite_driver.speed,
(u8)driver->max_speed);
composite = driver;
composite_gadget_bind = bind;
......
......@@ -165,28 +165,3 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
return ret;
}
/**
* usb_find_endpoint - find a copy of an endpoint descriptor
* @src: original vector of descriptors
* @copy: copy of @src
* @match: endpoint descriptor found in @src
*
* This returns the copy of the @match descriptor made for @copy. Its
* intended use is to help remembering the endpoint descriptor to use
* when enabling a given endpoint.
*/
struct usb_endpoint_descriptor *
usb_find_endpoint(
struct usb_descriptor_header **src,
struct usb_descriptor_header **copy,
struct usb_endpoint_descriptor *match
)
{
while (*src) {
if (*src == (void *) match)
return (void *)*copy;
src++;
copy++;
}
return NULL;
}
......@@ -173,7 +173,9 @@ static int dbgp_enable_ep_req(struct usb_ep *ep)
static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
{
int err = usb_ep_enable(ep, desc);
int err;
ep->desc = desc;
err = usb_ep_enable(ep);
ep->driver_data = dbgp.gadget;
return err;
}
......@@ -268,8 +270,8 @@ static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
dbgp.serial->in = dbgp.i_ep;
dbgp.serial->out = dbgp.o_ep;
dbgp.serial->in_desc = &i_desc;
dbgp.serial->out_desc = &o_desc;
dbgp.serial->in->desc = &i_desc;
dbgp.serial->out->desc = &o_desc;
if (gserial_setup(gadget, 1) < 0) {
stp = 3;
......@@ -312,7 +314,6 @@ static int __init dbgp_bind(struct usb_gadget *gadget)
dbgp.req->length = DBGP_REQ_EP0_LEN;
gadget->ep0->driver_data = gadget;
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
#ifdef CONFIG_USB_G_DBGP_SERIAL
dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
......@@ -363,6 +364,7 @@ static int dbgp_setup(struct usb_gadget *gadget,
dev_dbg(&dbgp.gadget->dev, "setup: desc device\n");
len = sizeof device_desc;
data = &device_desc;
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
break;
case USB_DT_DEBUG:
dev_dbg(&dbgp.gadget->dev, "setup: desc debug\n");
......
此差异已折叠。
......@@ -63,13 +63,16 @@ static int
ep_matches (
struct usb_gadget *gadget,
struct usb_ep *ep,
struct usb_endpoint_descriptor *desc
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp
)
{
u8 type;
const char *tmp;
u16 max;
int num_req_streams = 0;
/* endpoint already claimed? */
if (NULL != ep->driver_data)
return 0;
......@@ -128,6 +131,22 @@ ep_matches (
}
}
/*
* Get the number of required streams from the EP companion
* descriptor and see if the EP matches it
*/
if (usb_endpoint_xfer_bulk(desc)) {
if (ep_comp) {
num_req_streams = ep_comp->bmAttributes & 0x1f;
if (num_req_streams > ep->max_streams)
return 0;
/* Update the ep_comp descriptor if needed */
if (num_req_streams != ep->max_streams)
ep_comp->bmAttributes = ep->max_streams;
}
}
/*
* If the protocol driver hasn't yet decided on wMaxPacketSize
* and wants to know the maximum possible, provide the info.
......@@ -142,13 +161,13 @@ ep_matches (
max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
switch (type) {
case USB_ENDPOINT_XFER_INT:
/* INT: limit 64 bytes full speed, 1024 high speed */
/* INT: limit 64 bytes full speed, 1024 high/super speed */
if (!gadget->is_dualspeed && max > 64)
return 0;
/* FALLTHROUGH */
case USB_ENDPOINT_XFER_ISOC:
/* ISO: limit 1023 bytes full speed, 1024 high speed */
/* ISO: limit 1023 bytes full speed, 1024 high/super speed */
if (ep->maxpacket < max)
return 0;
if (!gadget->is_dualspeed && max > 1023)
......@@ -183,7 +202,7 @@ ep_matches (
}
/* report (variable) full speed bulk maxpacket */
if (USB_ENDPOINT_XFER_BULK == type) {
if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
int size = ep->maxpacket;
/* min() doesn't work on bitfields with gcc-3.5 */
......@@ -191,6 +210,7 @@ ep_matches (
size = 64;
desc->wMaxPacketSize = cpu_to_le16(size);
}
ep->address = desc->bEndpointAddress;
return 1;
}
......@@ -207,38 +227,53 @@ find_ep (struct usb_gadget *gadget, const char *name)
}
/**
* usb_ep_autoconfig - choose an endpoint matching the descriptor
* usb_ep_autoconfig_ss() - choose an endpoint matching the ep
* descriptor and ep companion descriptor
* @gadget: The device to which the endpoint must belong.
* @desc: Endpoint descriptor, with endpoint direction and transfer mode
* initialized. For periodic transfers, the maximum packet
* size must also be initialized. This is modified on success.
* initialized. For periodic transfers, the maximum packet
* size must also be initialized. This is modified on
* success.
* @ep_comp: Endpoint companion descriptor, with the required
* number of streams. Will be modified when the chosen EP
* supports a different number of streams.
*
* By choosing an endpoint to use with the specified descriptor, this
* routine simplifies writing gadget drivers that work with multiple
* USB device controllers. The endpoint would be passed later to
* usb_ep_enable(), along with some descriptor.
* This routine replaces the usb_ep_autoconfig when needed
* superspeed enhancments. If such enhancemnets are required,
* the FD should call usb_ep_autoconfig_ss directly and provide
* the additional ep_comp parameter.
*
* By choosing an endpoint to use with the specified descriptor,
* this routine simplifies writing gadget drivers that work with
* multiple USB device controllers. The endpoint would be
* passed later to usb_ep_enable(), along with some descriptor.
*
* That second descriptor won't always be the same as the first one.
* For example, isochronous endpoints can be autoconfigured for high
* bandwidth, and then used in several lower bandwidth altsettings.
* Also, high and full speed descriptors will be different.
*
* Be sure to examine and test the results of autoconfiguration on your
* hardware. This code may not make the best choices about how to use the
* USB controller, and it can't know all the restrictions that may apply.
* Some combinations of driver and hardware won't be able to autoconfigure.
* Be sure to examine and test the results of autoconfiguration
* on your hardware. This code may not make the best choices
* about how to use the USB controller, and it can't know all
* the restrictions that may apply. Some combinations of driver
* and hardware won't be able to autoconfigure.
*
* On success, this returns an un-claimed usb_ep, and modifies the endpoint
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
* is initialized as if the endpoint were used at full speed. To prevent
* the endpoint from being returned by a later autoconfig call, claim it
* by assigning ep->driver_data to some non-null value.
* is initialized as if the endpoint were used at full speed and
* the bmAttribute field in the ep companion descriptor is
* updated with the assigned number of streams if it is
* different from the original value. To prevent the endpoint
* from being returned by a later autoconfig call, claim it by
* assigning ep->driver_data to some non-null value.
*
* On failure, this returns a null endpoint descriptor.
*/
struct usb_ep *usb_ep_autoconfig (
struct usb_ep *usb_ep_autoconfig_ss(
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp
)
{
struct usb_ep *ep;
......@@ -252,23 +287,24 @@ struct usb_ep *usb_ep_autoconfig (
if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
/* ep-e, ep-f are PIO with only 64 byte fifos */
ep = find_ep (gadget, "ep-e");
if (ep && ep_matches (gadget, ep, desc))
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
ep = find_ep (gadget, "ep-f");
if (ep && ep_matches (gadget, ep, desc))
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
} else if (gadget_is_goku (gadget)) {
if (USB_ENDPOINT_XFER_INT == type) {
/* single buffering is enough */
ep = find_ep (gadget, "ep3-bulk");
if (ep && ep_matches (gadget, ep, desc))
ep = find_ep(gadget, "ep3-bulk");
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
} else if (USB_ENDPOINT_XFER_BULK == type
&& (USB_DIR_IN & desc->bEndpointAddress)) {
/* DMA may be available */
ep = find_ep (gadget, "ep2-bulk");
if (ep && ep_matches (gadget, ep, desc))
ep = find_ep(gadget, "ep2-bulk");
if (ep && ep_matches(gadget, ep, desc,
ep_comp))
return ep;
}
......@@ -287,14 +323,14 @@ struct usb_ep *usb_ep_autoconfig (
ep = find_ep(gadget, "ep2out");
} else
ep = NULL;
if (ep && ep_matches (gadget, ep, desc))
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
#endif
}
/* Second, look at endpoints until an unclaimed one looks usable */
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
if (ep_matches (gadget, ep, desc))
if (ep_matches(gadget, ep, desc, ep_comp))
return ep;
}
......@@ -302,6 +338,46 @@ struct usb_ep *usb_ep_autoconfig (
return NULL;
}
/**
* usb_ep_autoconfig() - choose an endpoint matching the
* descriptor
* @gadget: The device to which the endpoint must belong.
* @desc: Endpoint descriptor, with endpoint direction and transfer mode
* initialized. For periodic transfers, the maximum packet
* size must also be initialized. This is modified on success.
*
* By choosing an endpoint to use with the specified descriptor, this
* routine simplifies writing gadget drivers that work with multiple
* USB device controllers. The endpoint would be passed later to
* usb_ep_enable(), along with some descriptor.
*
* That second descriptor won't always be the same as the first one.
* For example, isochronous endpoints can be autoconfigured for high
* bandwidth, and then used in several lower bandwidth altsettings.
* Also, high and full speed descriptors will be different.
*
* Be sure to examine and test the results of autoconfiguration on your
* hardware. This code may not make the best choices about how to use the
* USB controller, and it can't know all the restrictions that may apply.
* Some combinations of driver and hardware won't be able to autoconfigure.
*
* On success, this returns an un-claimed usb_ep, and modifies the endpoint
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
* is initialized as if the endpoint were used at full speed. To prevent
* the endpoint from being returned by a later autoconfig call, claim it
* by assigning ep->driver_data to some non-null value.
*
* On failure, this returns a null endpoint descriptor.
*/
struct usb_ep *usb_ep_autoconfig(
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc
)
{
return usb_ep_autoconfig_ss(gadget, desc, NULL);
}
/**
* usb_ep_autoconfig_reset - reset endpoint autoconfig state
* @gadget: device for which autoconfig state will be reset
......
......@@ -401,6 +401,7 @@ static struct usb_composite_driver eth_driver = {
.name = "g_ether",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_SUPER,
.unbind = __exit_p(eth_unbind),
};
......
......@@ -39,12 +39,6 @@
* descriptors (roughly equivalent to CDC Unions) may sometimes help.
*/
struct acm_ep_descs {
struct usb_endpoint_descriptor *in;
struct usb_endpoint_descriptor *out;
struct usb_endpoint_descriptor *notify;
};
struct f_acm {
struct gserial port;
u8 ctrl_id, data_id;
......@@ -58,11 +52,7 @@ struct f_acm {
*/
spinlock_t lock;
struct acm_ep_descs fs;
struct acm_ep_descs hs;
struct usb_ep *notify;
struct usb_endpoint_descriptor *notify_desc;
struct usb_request *notify_req;
struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
......@@ -405,23 +395,27 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
usb_ep_disable(acm->notify);
} else {
VDBG(cdev, "init acm ctrl interface %d\n", intf);
acm->notify_desc = ep_choose(cdev->gadget,
acm->hs.notify,
acm->fs.notify);
if (config_ep_by_speed(cdev->gadget, f, acm->notify))
return -EINVAL;
}
usb_ep_enable(acm->notify, acm->notify_desc);
usb_ep_enable(acm->notify);
acm->notify->driver_data = acm;
} else if (intf == acm->data_id) {
if (acm->port.in->driver_data) {
DBG(cdev, "reset acm ttyGS%d\n", acm->port_num);
gserial_disconnect(&acm->port);
} else {
}
if (!acm->port.in->desc || !acm->port.out->desc) {
DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
acm->port.in_desc = ep_choose(cdev->gadget,
acm->hs.in, acm->fs.in);
acm->port.out_desc = ep_choose(cdev->gadget,
acm->hs.out, acm->fs.out);
if (config_ep_by_speed(cdev->gadget, f,
acm->port.in) ||
config_ep_by_speed(cdev->gadget, f,
acm->port.out)) {
acm->port.in->desc = NULL;
acm->port.out->desc = NULL;
return -EINVAL;
}
}
gserial_connect(&acm->port, acm->port_num);
......@@ -629,18 +623,11 @@ 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, and track endpoint copies */
/* copy descriptors */
f->descriptors = usb_copy_descriptors(acm_fs_function);
if (!f->descriptors)
goto fail;
acm->fs.in = usb_find_endpoint(acm_fs_function,
f->descriptors, &acm_fs_in_desc);
acm->fs.out = usb_find_endpoint(acm_fs_function,
f->descriptors, &acm_fs_out_desc);
acm->fs.notify = usb_find_endpoint(acm_fs_function,
f->descriptors, &acm_fs_notify_desc);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
......@@ -653,15 +640,8 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
acm_hs_notify_desc.bEndpointAddress =
acm_fs_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
/* copy descriptors */
f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
acm->hs.in = usb_find_endpoint(acm_hs_function,
f->hs_descriptors, &acm_hs_in_desc);
acm->hs.out = usb_find_endpoint(acm_hs_function,
f->hs_descriptors, &acm_hs_out_desc);
acm->hs.notify = usb_find_endpoint(acm_hs_function,
f->hs_descriptors, &acm_hs_notify_desc);
}
DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
......
......@@ -279,7 +279,6 @@ struct f_audio {
/* endpoints handle full and/or high speeds */
struct usb_ep *out_ep;
struct usb_endpoint_descriptor *out_desc;
spinlock_t lock;
struct f_audio_buf *copy_buf;
......@@ -575,7 +574,7 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (intf == 1) {
if (alt == 1) {
usb_ep_enable(out_ep, audio->out_desc);
usb_ep_enable(out_ep);
out_ep->driver_data = audio;
audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
if (IS_ERR(audio->copy_buf))
......@@ -677,6 +676,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
audio->out_ep = ep;
audio->out_ep->desc = &as_out_ep_desc;
ep->driver_data = cdev; /* claim */
status = -ENOMEM;
......@@ -776,7 +776,6 @@ int __init audio_bind_config(struct usb_configuration *c)
audio->card.func.set_alt = f_audio_set_alt;
audio->card.func.setup = f_audio_setup;
audio->card.func.disable = f_audio_disable;
audio->out_desc = &as_out_ep_desc;
control_selector_init(audio);
......
......@@ -46,11 +46,6 @@
* and also means that a get_alt() method is required.
*/
struct ecm_ep_descs {
struct usb_endpoint_descriptor *in;
struct usb_endpoint_descriptor *out;
struct usb_endpoint_descriptor *notify;
};
enum ecm_notify_state {
ECM_NOTIFY_NONE, /* don't notify */
......@@ -64,11 +59,7 @@ struct f_ecm {
char ethaddr[14];
struct ecm_ep_descs fs;
struct ecm_ep_descs hs;
struct usb_ep *notify;
struct usb_endpoint_descriptor *notify_desc;
struct usb_request *notify_req;
u8 notify_state;
bool is_open;
......@@ -86,10 +77,12 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f)
/* peak (theoretical) bulk transfer rate in bits-per-second */
static inline unsigned ecm_bitrate(struct usb_gadget *g)
{
if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
return 13 * 1024 * 8 * 1000 * 8;
else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
return 13 * 512 * 8 * 1000 * 8;
else
return 19 * 64 * 1 * 1000 * 8;
return 19 * 64 * 1 * 1000 * 8;
}
/*-------------------------------------------------------------------------*/
......@@ -219,8 +212,10 @@ static struct usb_descriptor_header *ecm_fs_function[] = {
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
(struct usb_descriptor_header *) &ecm_desc,
/* NOTE: status endpoint might need to be removed */
(struct usb_descriptor_header *) &fs_ecm_notify_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
......@@ -240,6 +235,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
......@@ -264,8 +260,10 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
(struct usb_descriptor_header *) &ecm_desc,
/* NOTE: status endpoint might need to be removed */
(struct usb_descriptor_header *) &hs_ecm_notify_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
......@@ -274,6 +272,76 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
NULL,
};
/* super speed support: */
static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
.bLength = sizeof ss_ecm_intr_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* the following 3 values can be tweaked if necessary */
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
.wBytesPerInterval = cpu_to_le16(ECM_STATUS_BYTECOUNT),
};
static struct usb_endpoint_descriptor ss_ecm_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_endpoint_descriptor ss_ecm_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
.bLength = sizeof ss_ecm_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* the following 2 values can be tweaked if necessary */
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
};
static struct usb_descriptor_header *ecm_ss_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
(struct usb_descriptor_header *) &ecm_desc,
/* NOTE: status endpoint might need to be removed */
(struct usb_descriptor_header *) &ss_ecm_notify_desc,
(struct usb_descriptor_header *) &ss_ecm_intr_comp_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
(struct usb_descriptor_header *) &ss_ecm_in_desc,
(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
(struct usb_descriptor_header *) &ss_ecm_out_desc,
(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
NULL,
};
/* string descriptors: */
static struct usb_string ecm_string_defs[] = {
......@@ -464,13 +532,13 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (ecm->notify->driver_data) {
VDBG(cdev, "reset ecm control %d\n", intf);
usb_ep_disable(ecm->notify);
} else {
}
if (!(ecm->notify->desc)) {
VDBG(cdev, "init ecm ctrl %d\n", intf);
ecm->notify_desc = ep_choose(cdev->gadget,
ecm->hs.notify,
ecm->fs.notify);
if (config_ep_by_speed(cdev->gadget, f, ecm->notify))
goto fail;
}
usb_ep_enable(ecm->notify, ecm->notify_desc);
usb_ep_enable(ecm->notify);
ecm->notify->driver_data = ecm;
/* Data interface has two altsettings, 0 and 1 */
......@@ -483,12 +551,17 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
gether_disconnect(&ecm->port);
}
if (!ecm->port.in) {
if (!ecm->port.in_ep->desc ||
!ecm->port.out_ep->desc) {
DBG(cdev, "init ecm\n");
ecm->port.in = ep_choose(cdev->gadget,
ecm->hs.in, ecm->fs.in);
ecm->port.out = ep_choose(cdev->gadget,
ecm->hs.out, ecm->fs.out);
if (config_ep_by_speed(cdev->gadget, f,
ecm->port.in_ep) ||
config_ep_by_speed(cdev->gadget, f,
ecm->port.out_ep)) {
ecm->port.in_ep->desc = NULL;
ecm->port.out_ep->desc = NULL;
goto fail;
}
}
/* CDC Ethernet only sends data in non-default altsettings.
......@@ -549,7 +622,7 @@ static void ecm_disable(struct usb_function *f)
if (ecm->notify->driver_data) {
usb_ep_disable(ecm->notify);
ecm->notify->driver_data = NULL;
ecm->notify_desc = NULL;
ecm->notify->desc = NULL;
}
}
......@@ -665,13 +738,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
if (!f->descriptors)
goto fail;
ecm->fs.in = usb_find_endpoint(ecm_fs_function,
f->descriptors, &fs_ecm_in_desc);
ecm->fs.out = usb_find_endpoint(ecm_fs_function,
f->descriptors, &fs_ecm_out_desc);
ecm->fs.notify = usb_find_endpoint(ecm_fs_function,
f->descriptors, &fs_ecm_notify_desc);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
......@@ -688,13 +754,20 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
if (!f->hs_descriptors)
goto fail;
}
ecm->hs.in = usb_find_endpoint(ecm_hs_function,
f->hs_descriptors, &hs_ecm_in_desc);
ecm->hs.out = usb_find_endpoint(ecm_hs_function,
f->hs_descriptors, &hs_ecm_out_desc);
ecm->hs.notify = usb_find_endpoint(ecm_hs_function,
f->hs_descriptors, &hs_ecm_notify_desc);
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;
}
/* NOTE: all that is done without knowing or caring about
......@@ -706,6 +779,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
ecm->port.close = ecm_close;
DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
ecm->port.in_ep->name, ecm->port.out_ep->name,
ecm->notify->name);
......@@ -714,6 +788,8 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
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);
......@@ -723,9 +799,9 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
/* we might as well release our claims on endpoints */
if (ecm->notify)
ecm->notify->driver_data = NULL;
if (ecm->port.out)
if (ecm->port.out_ep->desc)
ecm->port.out_ep->driver_data = NULL;
if (ecm->port.in)
if (ecm->port.in_ep->desc)
ecm->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
......@@ -740,6 +816,8 @@ 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);
......
......@@ -35,17 +35,9 @@
* Ethernet link.
*/
struct eem_ep_descs {
struct usb_endpoint_descriptor *in;
struct usb_endpoint_descriptor *out;
};
struct f_eem {
struct gether port;
u8 ctrl_id;
struct eem_ep_descs fs;
struct eem_ep_descs hs;
};
static inline struct f_eem *func_to_eem(struct usb_function *f)
......@@ -123,6 +115,45 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = {
NULL,
};
/* super speed support: */
static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = {
.bLength = sizeof eem_ss_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* the following 2 values can be tweaked if necessary */
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
};
static struct usb_descriptor_header *eem_ss_function[] __initdata = {
/* CDC EEM control descriptors */
(struct usb_descriptor_header *) &eem_intf,
(struct usb_descriptor_header *) &eem_ss_in_desc,
(struct usb_descriptor_header *) &eem_ss_bulk_comp_desc,
(struct usb_descriptor_header *) &eem_ss_out_desc,
(struct usb_descriptor_header *) &eem_ss_bulk_comp_desc,
NULL,
};
/* string descriptors: */
static struct usb_string eem_string_defs[] = {
......@@ -176,12 +207,16 @@ static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
gether_disconnect(&eem->port);
}
if (!eem->port.in) {
if (!eem->port.in_ep->desc || !eem->port.out_ep->desc) {
DBG(cdev, "init eem\n");
eem->port.in = ep_choose(cdev->gadget,
eem->hs.in, eem->fs.in);
eem->port.out = ep_choose(cdev->gadget,
eem->hs.out, eem->fs.out);
if (config_ep_by_speed(cdev->gadget, f,
eem->port.in_ep) ||
config_ep_by_speed(cdev->gadget, f,
eem->port.out_ep)) {
eem->port.in_ep->desc = NULL;
eem->port.out_ep->desc = NULL;
goto fail;
}
}
/* zlps should not occur because zero-length EEM packets
......@@ -253,11 +288,6 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
if (!f->descriptors)
goto fail;
eem->fs.in = usb_find_endpoint(eem_fs_function,
f->descriptors, &eem_fs_in_desc);
eem->fs.out = usb_find_endpoint(eem_fs_function,
f->descriptors, &eem_fs_out_desc);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
......@@ -272,14 +302,22 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
f->hs_descriptors = usb_copy_descriptors(eem_hs_function);
if (!f->hs_descriptors)
goto fail;
}
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;
eem->hs.in = usb_find_endpoint(eem_hs_function,
f->hs_descriptors, &eem_hs_in_desc);
eem->hs.out = usb_find_endpoint(eem_hs_function,
f->hs_descriptors, &eem_hs_out_desc);
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(eem_ss_function);
if (!f->ss_descriptors)
goto fail;
}
DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
eem->port.in_ep->name, eem->port.out_ep->name);
return 0;
......@@ -287,11 +325,13 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
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)
if (eem->port.out_ep->desc)
eem->port.out_ep->driver_data = NULL;
if (eem->port.in)
if (eem->port.in_ep->desc)
eem->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
......@@ -306,6 +346,8 @@ 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);
......
......@@ -1544,7 +1544,8 @@ static int ffs_func_eps_enable(struct ffs_function *func)
ds = ep->descs[ep->descs[1] ? 1 : 0];
ep->ep->driver_data = ep;
ret = usb_ep_enable(ep->ep, ds);
ep->ep->desc = ds;
ret = usb_ep_enable(ep->ep);
if (likely(!ret)) {
epfile->ep = ep;
epfile->in = usb_endpoint_dir_in(ds);
......
......@@ -59,8 +59,6 @@ struct f_hidg {
struct cdev cdev;
struct usb_function func;
struct usb_ep *in_ep;
struct usb_endpoint_descriptor *fs_in_ep_desc;
struct usb_endpoint_descriptor *hs_in_ep_desc;
};
static inline struct f_hidg *func_to_hidg(struct usb_function *f)
......@@ -416,7 +414,6 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = f->config->cdev;
struct f_hidg *hidg = func_to_hidg(f);
const struct usb_endpoint_descriptor *ep_desc;
int status = 0;
VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
......@@ -426,9 +423,13 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (hidg->in_ep->driver_data != NULL)
usb_ep_disable(hidg->in_ep);
ep_desc = ep_choose(f->config->cdev->gadget,
hidg->hs_in_ep_desc, hidg->fs_in_ep_desc);
status = usb_ep_enable(hidg->in_ep, ep_desc);
status = config_ep_by_speed(f->config->cdev->gadget, f,
hidg->in_ep);
if (status) {
ERROR(cdev, "config_ep_by_speed FAILED!\n");
goto fail;
}
status = usb_ep_enable(hidg->in_ep);
if (status < 0) {
ERROR(cdev, "Enable endpoint FAILED!\n");
goto fail;
......@@ -498,21 +499,12 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
if (!f->descriptors)
goto fail;
hidg->fs_in_ep_desc = usb_find_endpoint(hidg_fs_descriptors,
f->descriptors,
&hidg_fs_in_ep_desc);
if (gadget_is_dualspeed(c->cdev->gadget)) {
hidg_hs_in_ep_desc.bEndpointAddress =
hidg_fs_in_ep_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
if (!f->hs_descriptors)
goto fail;
hidg->hs_in_ep_desc = usb_find_endpoint(hidg_hs_descriptors,
f->hs_descriptors,
&hidg_hs_in_ep_desc);
} else {
hidg->hs_in_ep_desc = NULL;
}
mutex_init(&hidg->lock);
......
......@@ -118,6 +118,49 @@ static struct usb_descriptor_header *hs_loopback_descs[] = {
NULL,
};
/* super speed support: */
static struct usb_endpoint_descriptor ss_loop_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = 0,
};
static struct usb_endpoint_descriptor ss_loop_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = 0,
};
static struct usb_descriptor_header *ss_loopback_descs[] = {
(struct usb_descriptor_header *) &loopback_intf,
(struct usb_descriptor_header *) &ss_loop_source_desc,
(struct usb_descriptor_header *) &ss_loop_source_comp_desc,
(struct usb_descriptor_header *) &ss_loop_sink_desc,
(struct usb_descriptor_header *) &ss_loop_sink_comp_desc,
NULL,
};
/* function-specific strings: */
static struct usb_string strings_loopback[] = {
......@@ -175,8 +218,18 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
f->hs_descriptors = hs_loopback_descs;
}
/* 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;
}
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
(gadget_is_superspeed(c->cdev->gadget) ? "super" :
(gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
f->name, loop->in_ep->name, loop->out_ep->name);
return 0;
}
......@@ -250,26 +303,27 @@ static int
enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
{
int result = 0;
const struct usb_endpoint_descriptor *src, *sink;
struct usb_ep *ep;
struct usb_request *req;
unsigned i;
src = ep_choose(cdev->gadget,
&hs_loop_source_desc, &fs_loop_source_desc);
sink = ep_choose(cdev->gadget,
&hs_loop_sink_desc, &fs_loop_sink_desc);
/* one endpoint writes data back IN to the host */
ep = loop->in_ep;
result = usb_ep_enable(ep, src);
result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
if (result)
return result;
result = usb_ep_enable(ep);
if (result < 0)
return result;
ep->driver_data = loop;
/* one endpoint just reads OUT packets */
ep = loop->out_ep;
result = usb_ep_enable(ep, sink);
result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
if (result)
goto fail0;
result = usb_ep_enable(ep);
if (result < 0) {
fail0:
ep = loop->in_ep;
......
......@@ -2324,18 +2324,6 @@ static int get_next_command(struct fsg_common *common)
/*-------------------------------------------------------------------------*/
static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep,
const struct usb_endpoint_descriptor *d)
{
int rc;
ep->driver_data = common;
rc = usb_ep_enable(ep, d);
if (rc)
ERROR(common, "can't enable %s, result %d\n", ep->name, rc);
return rc;
}
static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
struct usb_request **preq)
{
......@@ -2349,7 +2337,6 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
/* Reset interface setting and re-init endpoint state (toggle etc). */
static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
{
const struct usb_endpoint_descriptor *d;
struct fsg_dev *fsg;
int i, rc = 0;
......@@ -2396,20 +2383,26 @@ static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
fsg = common->fsg;
/* Enable the endpoints */
d = fsg_ep_desc(common->gadget,
&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
rc = enable_endpoint(common, fsg->bulk_in, d);
rc = config_ep_by_speed(common->gadget, &(fsg->function), fsg->bulk_in);
if (rc)
goto reset;
rc = usb_ep_enable(fsg->bulk_in);
if (rc)
goto reset;
fsg->bulk_in->driver_data = common;
fsg->bulk_in_enabled = 1;
d = fsg_ep_desc(common->gadget,
&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
rc = enable_endpoint(common, fsg->bulk_out, d);
rc = config_ep_by_speed(common->gadget, &(fsg->function),
fsg->bulk_out);
if (rc)
goto reset;
rc = usb_ep_enable(fsg->bulk_out);
if (rc)
goto reset;
fsg->bulk_out->driver_data = common;
fsg->bulk_out_enabled = 1;
common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
common->bulk_out_maxpacket =
le16_to_cpu(fsg->bulk_out->desc->wMaxPacketSize);
clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
/* Allocate the requests */
......
......@@ -48,12 +48,6 @@
#define NCM_NDP_HDR_CRC 0x01000000
#define NCM_NDP_HDR_NOCRC 0x00000000
struct ncm_ep_descs {
struct usb_endpoint_descriptor *in;
struct usb_endpoint_descriptor *out;
struct usb_endpoint_descriptor *notify;
};
enum ncm_notify_state {
NCM_NOTIFY_NONE, /* don't notify */
NCM_NOTIFY_CONNECT, /* issue CONNECT next */
......@@ -66,11 +60,7 @@ struct f_ncm {
char ethaddr[14];
struct ncm_ep_descs fs;
struct ncm_ep_descs hs;
struct usb_ep *notify;
struct usb_endpoint_descriptor *notify_desc;
struct usb_request *notify_req;
u8 notify_state;
bool is_open;
......@@ -802,13 +792,14 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (ncm->notify->driver_data) {
DBG(cdev, "reset ncm control %d\n", intf);
usb_ep_disable(ncm->notify);
} else {
}
if (!(ncm->notify->desc)) {
DBG(cdev, "init ncm ctrl %d\n", intf);
ncm->notify_desc = ep_choose(cdev->gadget,
ncm->hs.notify,
ncm->fs.notify);
if (config_ep_by_speed(cdev->gadget, f, ncm->notify))
goto fail;
}
usb_ep_enable(ncm->notify, ncm->notify_desc);
usb_ep_enable(ncm->notify);
ncm->notify->driver_data = ncm;
/* Data interface has two altsettings, 0 and 1 */
......@@ -829,14 +820,17 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt == 1) {
struct net_device *net;
if (!ncm->port.in) {
if (!ncm->port.in_ep->desc ||
!ncm->port.out_ep->desc) {
DBG(cdev, "init ncm\n");
ncm->port.in = ep_choose(cdev->gadget,
ncm->hs.in,
ncm->fs.in);
ncm->port.out = ep_choose(cdev->gadget,
ncm->hs.out,
ncm->fs.out);
if (config_ep_by_speed(cdev->gadget, f,
ncm->port.in_ep) ||
config_ep_by_speed(cdev->gadget, f,
ncm->port.out_ep)) {
ncm->port.in_ep->desc = NULL;
ncm->port.out_ep->desc = NULL;
goto fail;
}
}
/* TODO */
......@@ -1111,7 +1105,7 @@ static void ncm_disable(struct usb_function *f)
if (ncm->notify->driver_data) {
usb_ep_disable(ncm->notify);
ncm->notify->driver_data = NULL;
ncm->notify_desc = NULL;
ncm->notify->desc = NULL;
}
}
......@@ -1228,13 +1222,6 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
if (!f->descriptors)
goto fail;
ncm->fs.in = usb_find_endpoint(ncm_fs_function,
f->descriptors, &fs_ncm_in_desc);
ncm->fs.out = usb_find_endpoint(ncm_fs_function,
f->descriptors, &fs_ncm_out_desc);
ncm->fs.notify = usb_find_endpoint(ncm_fs_function,
f->descriptors, &fs_ncm_notify_desc);
/*
* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
......@@ -1252,13 +1239,6 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
f->hs_descriptors = usb_copy_descriptors(ncm_hs_function);
if (!f->hs_descriptors)
goto fail;
ncm->hs.in = usb_find_endpoint(ncm_hs_function,
f->hs_descriptors, &hs_ncm_in_desc);
ncm->hs.out = usb_find_endpoint(ncm_hs_function,
f->hs_descriptors, &hs_ncm_out_desc);
ncm->hs.notify = usb_find_endpoint(ncm_hs_function,
f->hs_descriptors, &hs_ncm_notify_desc);
}
/*
......@@ -1288,9 +1268,9 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
/* we might as well release our claims on endpoints */
if (ncm->notify)
ncm->notify->driver_data = NULL;
if (ncm->port.out)
if (ncm->port.out_ep->desc)
ncm->port.out_ep->driver_data = NULL;
if (ncm->port.in)
if (ncm->port.in_ep->desc)
ncm->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
......
......@@ -39,20 +39,12 @@
* ready to handle the commands.
*/
struct obex_ep_descs {
struct usb_endpoint_descriptor *obex_in;
struct usb_endpoint_descriptor *obex_out;
};
struct f_obex {
struct gserial port;
u8 ctrl_id;
u8 data_id;
u8 port_num;
u8 can_activate;
struct obex_ep_descs fs;
struct obex_ep_descs hs;
};
static inline struct f_obex *func_to_obex(struct usb_function *f)
......@@ -227,12 +219,16 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
gserial_disconnect(&obex->port);
}
if (!obex->port.in_desc) {
if (!obex->port.in->desc || !obex->port.out->desc) {
DBG(cdev, "init obex ttyGS%d\n", obex->port_num);
obex->port.in_desc = ep_choose(cdev->gadget,
obex->hs.obex_in, obex->fs.obex_in);
obex->port.out_desc = ep_choose(cdev->gadget,
obex->hs.obex_out, obex->fs.obex_out);
if (config_ep_by_speed(cdev->gadget, f,
obex->port.in) ||
config_ep_by_speed(cdev->gadget, f,
obex->port.out)) {
obex->port.out->desc = NULL;
obex->port.in->desc = NULL;
goto fail;
}
}
if (alt == 1) {
......@@ -346,11 +342,6 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(fs_function);
obex->fs.obex_in = usb_find_endpoint(fs_function,
f->descriptors, &obex_fs_ep_in_desc);
obex->fs.obex_out = usb_find_endpoint(fs_function,
f->descriptors, &obex_fs_ep_out_desc);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
......@@ -364,11 +355,6 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(hs_function);
obex->hs.obex_in = usb_find_endpoint(hs_function,
f->hs_descriptors, &obex_hs_ep_in_desc);
obex->hs.obex_out = usb_find_endpoint(hs_function,
f->hs_descriptors, &obex_hs_ep_out_desc);
}
/* Avoid letting this gadget enumerate until the userspace
......
......@@ -428,17 +428,16 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
spin_lock(&port->lock);
__pn_reset(f);
if (alt == 1) {
struct usb_endpoint_descriptor *out, *in;
int i;
out = ep_choose(gadget,
&pn_hs_sink_desc,
&pn_fs_sink_desc);
in = ep_choose(gadget,
&pn_hs_source_desc,
&pn_fs_source_desc);
usb_ep_enable(fp->out_ep, out);
usb_ep_enable(fp->in_ep, in);
if (config_ep_by_speed(gadget, f, fp->in_ep) ||
config_ep_by_speed(gadget, f, fp->out_ep)) {
fp->in_ep->desc = NULL;
fp->out_ep->desc = NULL;
return -EINVAL;
}
usb_ep_enable(fp->out_ep);
usb_ep_enable(fp->in_ep);
port->usb = fp;
fp->out_ep->driver_data = fp;
......
此差异已折叠。
......@@ -27,18 +27,10 @@
* if you can arrange appropriate host side drivers.
*/
struct gser_descs {
struct usb_endpoint_descriptor *in;
struct usb_endpoint_descriptor *out;
};
struct f_gser {
struct gserial port;
u8 data_id;
u8 port_num;
struct gser_descs fs;
struct gser_descs hs;
};
static inline struct f_gser *func_to_gser(struct usb_function *f)
......@@ -136,12 +128,15 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (gser->port.in->driver_data) {
DBG(cdev, "reset generic ttyGS%d\n", gser->port_num);
gserial_disconnect(&gser->port);
} else {
}
if (!gser->port.in->desc || !gser->port.out->desc) {
DBG(cdev, "activate generic ttyGS%d\n", gser->port_num);
gser->port.in_desc = ep_choose(cdev->gadget,
gser->hs.in, gser->fs.in);
gser->port.out_desc = ep_choose(cdev->gadget,
gser->hs.out, gser->fs.out);
if (!config_ep_by_speed(cdev->gadget, f, gser->port.in) ||
!config_ep_by_speed(cdev->gadget, f, gser->port.out)) {
gser->port.in->desc = NULL;
gser->port.out->desc = NULL;
return -EINVAL;
}
}
gserial_connect(&gser->port, gser->port_num);
return 0;
......@@ -193,12 +188,6 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(gser_fs_function);
gser->fs.in = usb_find_endpoint(gser_fs_function,
f->descriptors, &gser_fs_in_desc);
gser->fs.out = usb_find_endpoint(gser_fs_function,
f->descriptors, &gser_fs_out_desc);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
......@@ -211,11 +200,6 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
gser->hs.in = usb_find_endpoint(gser_hs_function,
f->hs_descriptors, &gser_hs_in_desc);
gser->hs.out = usb_find_endpoint(gser_hs_function,
f->hs_descriptors, &gser_hs_out_desc);
}
DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
......
......@@ -131,6 +131,49 @@ static struct usb_descriptor_header *hs_source_sink_descs[] = {
NULL,
};
/* super speed support: */
static struct usb_endpoint_descriptor ss_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
struct usb_ss_ep_comp_descriptor ss_source_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = 0,
};
static struct usb_endpoint_descriptor ss_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = {
.bLength = USB_DT_SS_EP_COMP_SIZE,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = 0,
};
static struct usb_descriptor_header *ss_source_sink_descs[] = {
(struct usb_descriptor_header *) &source_sink_intf,
(struct usb_descriptor_header *) &ss_source_desc,
(struct usb_descriptor_header *) &ss_source_comp_desc,
(struct usb_descriptor_header *) &ss_sink_desc,
(struct usb_descriptor_header *) &ss_sink_comp_desc,
NULL,
};
/* function-specific strings: */
static struct usb_string strings_sourcesink[] = {
......@@ -187,8 +230,18 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
f->hs_descriptors = hs_source_sink_descs;
}
/* 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;
f->ss_descriptors = ss_source_sink_descs;
}
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
(gadget_is_superspeed(c->cdev->gadget) ? "super" :
(gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
f->name, ss->in_ep->name, ss->out_ep->name);
return 0;
}
......@@ -343,15 +396,14 @@ static int
enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
{
int result = 0;
const struct usb_endpoint_descriptor *src, *sink;
struct usb_ep *ep;
src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
/* one endpoint writes (sources) zeroes IN (to the host) */
ep = ss->in_ep;
result = usb_ep_enable(ep, src);
result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
if (result)
return result;
result = usb_ep_enable(ep);
if (result < 0)
return result;
ep->driver_data = ss;
......@@ -367,7 +419,10 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
/* one endpoint reads (sinks) anything OUT (from the host) */
ep = ss->out_ep;
result = usb_ep_enable(ep, sink);
result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
if (result)
goto fail;
result = usb_ep_enable(ep);
if (result < 0)
goto fail;
ep->driver_data = ss;
......@@ -435,6 +490,8 @@ static int sourcesink_setup(struct usb_configuration *c,
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
req->length = USB_BUFSIZ;
/* composite driver infrastructure handles everything except
* the two control test requests.
*/
......
此差异已折叠。
......@@ -262,8 +262,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (uvc->state != UVC_STATE_CONNECTED)
return 0;
if (uvc->video.ep)
usb_ep_enable(uvc->video.ep, &uvc_streaming_ep);
if (uvc->video.ep) {
uvc->video.ep->desc = &uvc_streaming_ep;
usb_ep_enable(uvc->video.ep);
}
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON;
......@@ -649,7 +651,7 @@ uvc_bind_config(struct usb_configuration *c,
if (ret)
kfree(uvc);
return 0;
return ret;
error:
kfree(uvc);
......
......@@ -929,6 +929,7 @@ static int standard_setup_req(struct fsg_dev *fsg,
case USB_DT_DEVICE:
VDBG(fsg, "get device descriptor\n");
device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
value = sizeof device_desc;
memcpy(req->buf, &device_desc, value);
break;
......@@ -936,6 +937,11 @@ static int standard_setup_req(struct fsg_dev *fsg,
VDBG(fsg, "get device qualifier\n");
if (!gadget_is_dualspeed(fsg->gadget))
break;
/*
* Assume ep0 uses the same maxpacket value for both
* speeds
*/
dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
value = sizeof dev_qualifier;
memcpy(req->buf, &dev_qualifier, value);
break;
......@@ -2713,7 +2719,8 @@ static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
int rc;
ep->driver_data = fsg;
rc = usb_ep_enable(ep, d);
ep->desc = d;
rc = usb_ep_enable(ep);
if (rc)
ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
return rc;
......@@ -3416,7 +3423,6 @@ static int __init fsg_bind(struct usb_gadget *gadget)
}
/* Fix up the descriptors */
device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
device_desc.idVendor = cpu_to_le16(mod_data.vendor);
device_desc.idProduct = cpu_to_le16(mod_data.product);
device_desc.bcdDevice = cpu_to_le16(mod_data.release);
......@@ -3430,9 +3436,6 @@ static int __init fsg_bind(struct usb_gadget *gadget)
if (gadget_is_dualspeed(gadget)) {
fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
/* Assume ep0 uses the same maxpacket value for both speeds */
dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
/* Assume endpoint addresses are the same for both speeds */
fsg_hs_bulk_in_desc.bEndpointAddress =
fsg_fs_bulk_in_desc.bEndpointAddress;
......@@ -3486,6 +3489,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
}
INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
INFO(fsg, "NOTE: This driver is deprecated. "
"Consider using g_mass_storage instead.\n");
INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -162,6 +162,7 @@ static struct usb_composite_driver gfs_driver = {
.name = DRIVER_NAME,
.dev = &gfs_dev_desc,
.strings = gfs_dev_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = gfs_unbind,
.iProduct = DRIVER_DESC,
};
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册