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
This commit is contained in:
Linus Torvalds 2011-07-25 23:08:32 -07:00
Родитель f0deb97ab1 e04f5f7e42
Коммит f549953c15
135 изменённых файлов: 9145 добавлений и 3227 удалений

Просмотреть файл

@ -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.
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_RENESAS_USBHS_UDC
tristate
depends on USB_GADGET_RENESAS_USBHS
default USB_GADGET
select USB_GADGET_SELECTED
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.
config USB_GADGET_NET2280
boolean "NetChip 228x"
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.
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 @@ out:
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 @@ err_driver_bind:
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 @@ fail_1:
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,7 +227,120 @@ 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.
* @ep_comp: Endpoint companion descriptor, with the required
* number of streams. Will be modified when the chosen EP
* supports a different number of streams.
*
* 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.
*
* 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 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_ss(
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp
)
{
struct usb_ep *ep;
u8 type;
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
/* First, apply chip-specific "best usage" knowledge.
* This might make a good usb_gadget_ops hook ...
*/
if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
/* ep-e, ep-f are PIO with only 64 byte fifos */
ep = find_ep (gadget, "ep-e");
if (ep && ep_matches(gadget, ep, desc, ep_comp))
return ep;
ep = find_ep (gadget, "ep-f");
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_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_comp))
return ep;
}
#ifdef CONFIG_BLACKFIN
} else if (gadget_is_musbhdrc(gadget)) {
if ((USB_ENDPOINT_XFER_BULK == type) ||
(USB_ENDPOINT_XFER_ISOC == type)) {
if (USB_DIR_IN & desc->bEndpointAddress)
ep = find_ep (gadget, "ep5in");
else
ep = find_ep (gadget, "ep6out");
} else if (USB_ENDPOINT_XFER_INT == type) {
if (USB_DIR_IN & desc->bEndpointAddress)
ep = find_ep(gadget, "ep1in");
else
ep = find_ep(gadget, "ep2out");
} else
ep = NULL;
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, ep_comp))
return ep;
}
/* Fail */
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
@ -236,72 +369,15 @@ find_ep (struct usb_gadget *gadget, const char *name)
*
* On failure, this returns a null endpoint descriptor.
*/
struct usb_ep *usb_ep_autoconfig (
struct usb_ep *usb_ep_autoconfig(
struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc
)
{
struct usb_ep *ep;
u8 type;
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
/* First, apply chip-specific "best usage" knowledge.
* This might make a good usb_gadget_ops hook ...
*/
if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
/* ep-e, ep-f are PIO with only 64 byte fifos */
ep = find_ep (gadget, "ep-e");
if (ep && ep_matches (gadget, ep, desc))
return ep;
ep = find_ep (gadget, "ep-f");
if (ep && ep_matches (gadget, ep, desc))
return ep;
} else if (gadget_is_goku (gadget)) {
if (USB_ENDPOINT_XFER_INT == type) {
/* single buffering is enough */
ep = find_ep (gadget, "ep3-bulk");
if (ep && ep_matches (gadget, ep, desc))
return ep;
} else if (USB_ENDPOINT_XFER_BULK == type
&& (USB_DIR_IN & desc->bEndpointAddress)) {
/* DMA may be available */
ep = find_ep (gadget, "ep2-bulk");
if (ep && ep_matches (gadget, ep, desc))
return ep;
}
#ifdef CONFIG_BLACKFIN
} else if (gadget_is_musbhdrc(gadget)) {
if ((USB_ENDPOINT_XFER_BULK == type) ||
(USB_ENDPOINT_XFER_ISOC == type)) {
if (USB_DIR_IN & desc->bEndpointAddress)
ep = find_ep (gadget, "ep5in");
else
ep = find_ep (gadget, "ep6out");
} else if (USB_ENDPOINT_XFER_INT == type) {
if (USB_DIR_IN & desc->bEndpointAddress)
ep = find_ep(gadget, "ep1in");
else
ep = find_ep(gadget, "ep2out");
} else
ep = NULL;
if (ep && ep_matches (gadget, ep, desc))
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))
return ep;
}
/* Fail */
return NULL;
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 {
VDBG(cdev, "init ecm ctrl %d\n", intf);
ecm->notify_desc = ep_choose(cdev->gadget,
ecm->hs.notify,
ecm->fs.notify);
}
usb_ep_enable(ecm->notify, ecm->notify_desc);
if (!(ecm->notify->desc)) {
VDBG(cdev, "init ecm ctrl %d\n", intf);
if (config_ep_by_speed(cdev->gadget, f, ecm->notify))
goto fail;
}
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 @@ fail:
/* 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;
}
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);
if (gadget_is_superspeed(c->cdev->gadget)) {
eem_ss_in_desc.bEndpointAddress =
eem_fs_in_desc.bEndpointAddress;
eem_ss_out_desc.bEndpointAddress =
eem_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(eem_ss_function);
if (!f->ss_descriptors)
goto fail;
}
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 @@ autoconf_fail:
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 @@ reset:
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 {
DBG(cdev, "init ncm ctrl %d\n", intf);
ncm->notify_desc = ep_choose(cdev->gadget,
ncm->hs.notify,
ncm->fs.notify);
}
usb_ep_enable(ncm->notify, ncm->notify_desc);
if (!(ncm->notify->desc)) {
DBG(cdev, "init ncm ctrl %d\n", intf);
if (config_ep_by_speed(cdev->gadget, f, ncm->notify))
goto fail;
}
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 @@ fail:
/* 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;

Просмотреть файл

@ -76,23 +76,13 @@
* - MS-Windows drivers sometimes emit undocumented requests.
*/
struct rndis_ep_descs {
struct usb_endpoint_descriptor *in;
struct usb_endpoint_descriptor *out;
struct usb_endpoint_descriptor *notify;
};
struct f_rndis {
struct gether port;
u8 ctrl_id, data_id;
u8 ethaddr[ETH_ALEN];
int config;
struct rndis_ep_descs fs;
struct rndis_ep_descs hs;
struct usb_ep *notify;
struct usb_endpoint_descriptor *notify_desc;
struct usb_request *notify_req;
atomic_t notify_count;
};
@ -105,10 +95,12 @@ static inline struct f_rndis *func_to_rndis(struct usb_function *f)
/* peak (theoretical) bulk transfer rate in bits-per-second */
static unsigned int 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;
}
/*-------------------------------------------------------------------------*/
@ -226,6 +218,7 @@ static struct usb_endpoint_descriptor fs_out_desc = {
static struct usb_descriptor_header *eth_fs_function[] = {
(struct usb_descriptor_header *) &rndis_iad_descriptor,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
(struct usb_descriptor_header *) &header_desc,
@ -233,6 +226,7 @@ static struct usb_descriptor_header *eth_fs_function[] = {
(struct usb_descriptor_header *) &rndis_acm_descriptor,
(struct usb_descriptor_header *) &rndis_union_desc,
(struct usb_descriptor_header *) &fs_notify_desc,
/* data interface has no altsetting */
(struct usb_descriptor_header *) &rndis_data_intf,
(struct usb_descriptor_header *) &fs_in_desc,
@ -251,6 +245,7 @@ static struct usb_endpoint_descriptor hs_notify_desc = {
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -271,6 +266,7 @@ static struct usb_endpoint_descriptor hs_out_desc = {
static struct usb_descriptor_header *eth_hs_function[] = {
(struct usb_descriptor_header *) &rndis_iad_descriptor,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
(struct usb_descriptor_header *) &header_desc,
@ -278,6 +274,7 @@ static struct usb_descriptor_header *eth_hs_function[] = {
(struct usb_descriptor_header *) &rndis_acm_descriptor,
(struct usb_descriptor_header *) &rndis_union_desc,
(struct usb_descriptor_header *) &hs_notify_desc,
/* data interface has no altsetting */
(struct usb_descriptor_header *) &rndis_data_intf,
(struct usb_descriptor_header *) &hs_in_desc,
@ -285,6 +282,76 @@ static struct usb_descriptor_header *eth_hs_function[] = {
NULL,
};
/* super speed support: */
static struct usb_endpoint_descriptor ss_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = {
.bLength = sizeof ss_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(STATUS_BYTECOUNT),
};
static struct usb_endpoint_descriptor ss_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_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_bulk_comp_desc = {
.bLength = sizeof 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 *eth_ss_function[] = {
(struct usb_descriptor_header *) &rndis_iad_descriptor,
/* control interface matches ACM, not Ethernet */
(struct usb_descriptor_header *) &rndis_control_intf,
(struct usb_descriptor_header *) &header_desc,
(struct usb_descriptor_header *) &call_mgmt_descriptor,
(struct usb_descriptor_header *) &rndis_acm_descriptor,
(struct usb_descriptor_header *) &rndis_union_desc,
(struct usb_descriptor_header *) &ss_notify_desc,
(struct usb_descriptor_header *) &ss_intr_comp_desc,
/* data interface has no altsetting */
(struct usb_descriptor_header *) &rndis_data_intf,
(struct usb_descriptor_header *) &ss_in_desc,
(struct usb_descriptor_header *) &ss_bulk_comp_desc,
(struct usb_descriptor_header *) &ss_out_desc,
(struct usb_descriptor_header *) &ss_bulk_comp_desc,
NULL,
};
/* string descriptors: */
static struct usb_string rndis_string_defs[] = {
@ -484,13 +551,13 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (rndis->notify->driver_data) {
VDBG(cdev, "reset rndis control %d\n", intf);
usb_ep_disable(rndis->notify);
} else {
VDBG(cdev, "init rndis ctrl %d\n", intf);
rndis->notify_desc = ep_choose(cdev->gadget,
rndis->hs.notify,
rndis->fs.notify);
}
usb_ep_enable(rndis->notify, rndis->notify_desc);
if (!rndis->notify->desc) {
VDBG(cdev, "init rndis ctrl %d\n", intf);
if (config_ep_by_speed(cdev->gadget, f, rndis->notify))
goto fail;
}
usb_ep_enable(rndis->notify);
rndis->notify->driver_data = rndis;
} else if (intf == rndis->data_id) {
@ -501,12 +568,16 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
gether_disconnect(&rndis->port);
}
if (!rndis->port.in) {
if (!rndis->port.in_ep->desc || !rndis->port.out_ep->desc) {
DBG(cdev, "init rndis\n");
rndis->port.in = ep_choose(cdev->gadget,
rndis->hs.in, rndis->fs.in);
rndis->port.out = ep_choose(cdev->gadget,
rndis->hs.out, rndis->fs.out);
if (config_ep_by_speed(cdev->gadget, f,
rndis->port.in_ep) ||
config_ep_by_speed(cdev->gadget, f,
rndis->port.out_ep)) {
rndis->port.in_ep->desc = NULL;
rndis->port.out_ep->desc = NULL;
goto fail;
}
}
/* Avoid ZLPs; they can be troublesome. */
@ -662,13 +733,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
if (!f->descriptors)
goto fail;
rndis->fs.in = usb_find_endpoint(eth_fs_function,
f->descriptors, &fs_in_desc);
rndis->fs.out = usb_find_endpoint(eth_fs_function,
f->descriptors, &fs_out_desc);
rndis->fs.notify = usb_find_endpoint(eth_fs_function,
f->descriptors, &fs_notify_desc);
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
@ -683,16 +747,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
if (!f->hs_descriptors)
goto fail;
}
rndis->hs.in = usb_find_endpoint(eth_hs_function,
f->hs_descriptors, &hs_in_desc);
rndis->hs.out = usb_find_endpoint(eth_hs_function,
f->hs_descriptors, &hs_out_desc);
rndis->hs.notify = usb_find_endpoint(eth_hs_function,
f->hs_descriptors, &hs_notify_desc);
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_in_desc.bEndpointAddress =
fs_in_desc.bEndpointAddress;
ss_out_desc.bEndpointAddress =
fs_out_desc.bEndpointAddress;
ss_notify_desc.bEndpointAddress =
fs_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(eth_ss_function);
if (!f->ss_descriptors)
goto fail;
}
rndis->port.open = rndis_open;
@ -719,12 +789,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
*/
DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
rndis->port.in_ep->name, rndis->port.out_ep->name,
rndis->notify->name);
return 0;
fail:
if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors)
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
if (f->descriptors)
@ -738,9 +811,9 @@ fail:
/* we might as well release our claims on endpoints */
if (rndis->notify)
rndis->notify->driver_data = NULL;
if (rndis->port.out)
if (rndis->port.out_ep->desc)
rndis->port.out_ep->driver_data = NULL;
if (rndis->port.in)
if (rndis->port.in_ep->desc)
rndis->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@ -756,6 +829,8 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
rndis_deregister(rndis->config);
rndis_exit();
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);

Просмотреть файл

@ -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 @@ autoconf_fail:
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 @@ fail:
/* 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.
*/

Просмотреть файл

@ -57,18 +57,10 @@
* caring about specific product and vendor IDs.
*/
struct geth_descs {
struct usb_endpoint_descriptor *in;
struct usb_endpoint_descriptor *out;
};
struct f_gether {
struct gether port;
char ethaddr[14];
struct geth_descs fs;
struct geth_descs hs;
};
static inline struct f_gether *func_to_geth(struct usb_function *f)
@ -209,6 +201,46 @@ static struct usb_descriptor_header *hs_eth_function[] __initdata = {
NULL,
};
/* super speed support: */
static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = {
.bLength = sizeof ss_subset_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 *ss_eth_function[] __initdata = {
(struct usb_descriptor_header *) &subset_data_intf,
(struct usb_descriptor_header *) &mdlm_header_desc,
(struct usb_descriptor_header *) &mdlm_desc,
(struct usb_descriptor_header *) &mdlm_detail_desc,
(struct usb_descriptor_header *) &ether_desc,
(struct usb_descriptor_header *) &ss_subset_in_desc,
(struct usb_descriptor_header *) &ss_subset_bulk_comp_desc,
(struct usb_descriptor_header *) &ss_subset_out_desc,
(struct usb_descriptor_header *) &ss_subset_bulk_comp_desc,
NULL,
};
/* string descriptors: */
static struct usb_string geth_string_defs[] = {
@ -243,10 +275,12 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
}
DBG(cdev, "init + activate cdc subset\n");
geth->port.in = ep_choose(cdev->gadget,
geth->hs.in, geth->fs.in);
geth->port.out = ep_choose(cdev->gadget,
geth->hs.out, geth->fs.out);
if (config_ep_by_speed(cdev->gadget, f, geth->port.in_ep) ||
config_ep_by_speed(cdev->gadget, f, geth->port.out_ep)) {
geth->port.in_ep->desc = NULL;
geth->port.out_ep->desc = NULL;
return -EINVAL;
}
net = gether_connect(&geth->port);
return IS_ERR(net) ? PTR_ERR(net) : 0;
@ -296,12 +330,8 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(fs_eth_function);
geth->fs.in = usb_find_endpoint(fs_eth_function,
f->descriptors, &fs_subset_in_desc);
geth->fs.out = usb_find_endpoint(fs_eth_function,
f->descriptors, &fs_subset_out_desc);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
@ -315,11 +345,20 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
if (!f->hs_descriptors)
goto fail;
}
geth->hs.in = usb_find_endpoint(hs_eth_function,
f->hs_descriptors, &hs_subset_in_desc);
geth->hs.out = usb_find_endpoint(hs_eth_function,
f->hs_descriptors, &hs_subset_out_desc);
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_subset_in_desc.bEndpointAddress =
fs_subset_in_desc.bEndpointAddress;
ss_subset_out_desc.bEndpointAddress =
fs_subset_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(ss_eth_function);
if (!f->ss_descriptors)
goto fail;
}
/* NOTE: all that is done without knowing or caring about
@ -328,15 +367,21 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
*/
DBG(cdev, "CDC Subset: %s speed IN/%s OUT/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
geth->port.in_ep->name, geth->port.out_ep->name);
return 0;
fail:
if (f->descriptors)
usb_free_descriptors(f->descriptors);
if (f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
/* we might as well release our claims on endpoints */
if (geth->port.out)
if (geth->port.out_ep->desc)
geth->port.out_ep->driver_data = NULL;
if (geth->port.in)
if (geth->port.in_ep->desc)
geth->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@ -347,6 +392,8 @@ fail:
static void
geth_unbind(struct usb_configuration *c, struct usb_function *f)
{
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);

Просмотреть файл

@ -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);

Просмотреть файл

@ -1927,6 +1927,10 @@ static int qe_pullup(struct usb_gadget *gadget, int is_on)
return -ENOTSUPP;
}
static int fsl_qe_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int fsl_qe_stop(struct usb_gadget_driver *driver);
/* defined in usb_gadget.h */
static struct usb_gadget_ops qe_gadget_ops = {
.get_frame = qe_get_frame,
@ -1935,6 +1939,8 @@ static struct usb_gadget_ops qe_gadget_ops = {
.vbus_session = qe_vbus_session,
.vbus_draw = qe_vbus_draw,
.pullup = qe_pullup,
.start = fsl_qe_start,
.stop = fsl_qe_stop,
};
/*-------------------------------------------------------------------------
@ -2320,7 +2326,7 @@ static irqreturn_t qe_udc_irq(int irq, void *_udc)
/*-------------------------------------------------------------------------
Gadget driver probe and unregister.
--------------------------------------------------------------------------*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int fsl_qe_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
int retval;
@ -2369,9 +2375,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
udc_controller->gadget.name, driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int fsl_qe_stop(struct usb_gadget_driver *driver)
{
struct qe_ep *loop_ep;
unsigned long flags;
@ -2411,7 +2416,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/* udc structure's alloc and setup, include ep-param alloc */
static struct qe_udc __devinit *qe_udc_config(struct platform_device *ofdev)
@ -2662,11 +2666,17 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev)
if (ret)
goto err6;
ret = usb_add_gadget_udc(&ofdev->dev, &udc_controller->gadget);
if (ret)
goto err7;
dev_info(udc_controller->dev,
"%s USB controller initialized as device\n",
(udc_controller->soc_type == PORT_QE) ? "QE" : "CPM");
return 0;
err7:
device_unregister(&udc_controller->gadget.dev);
err6:
free_irq(udc_controller->usb_irq, udc_controller);
err5:
@ -2721,6 +2731,8 @@ static int __devexit qe_udc_remove(struct platform_device *ofdev)
if (!udc_controller)
return -ENODEV;
usb_del_gadget_udc(&udc_controller->gadget);
udc_controller->done = &done;
tasklet_disable(&udc_controller->rx_tasklet);

Просмотреть файл

@ -1244,6 +1244,9 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
static int fsl_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int fsl_stop(struct usb_gadget_driver *driver);
/* defined in gadget.h */
static struct usb_gadget_ops fsl_gadget_ops = {
.get_frame = fsl_get_frame,
@ -1252,6 +1255,8 @@ static struct usb_gadget_ops fsl_gadget_ops = {
.vbus_session = fsl_vbus_session,
.vbus_draw = fsl_vbus_draw,
.pullup = fsl_pullup,
.start = fsl_start,
.stop = fsl_stop,
};
/* Set protocol stall on ep0, protocol stall will automatically be cleared
@ -1927,7 +1932,7 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
* Hook to gadget drivers
* Called by initialization code of gadget drivers
*----------------------------------------------------------------*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int fsl_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
int retval = -ENODEV;
@ -1995,10 +2000,9 @@ out:
retval);
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
/* Disconnect from gadget driver */
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int fsl_stop(struct usb_gadget_driver *driver)
{
struct fsl_ep *loop_ep;
unsigned long flags;
@ -2041,7 +2045,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------
PROC File System Support
@ -2590,9 +2593,16 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto err_unregister;
}
ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
if (ret)
goto err_del_udc;
create_proc_file();
return 0;
err_del_udc:
dma_pool_destroy(udc_controller->td_pool);
err_unregister:
device_unregister(&udc_controller->gadget.dev);
err_free_irq:
@ -2624,6 +2634,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
if (!udc_controller)
return -ENODEV;
usb_del_gadget_udc(&udc_controller->gadget);
udc_controller->done = &done;
fsl_udc_clk_release();

Просмотреть файл

@ -767,56 +767,6 @@ static void fusb300_rdfifo(struct fusb300_ep *ep,
} while (!reg);
}
/* write data to fifo */
static void fusb300_wrfifo(struct fusb300_ep *ep,
struct fusb300_request *req)
{
int i = 0;
u8 *tmp;
u32 data, reg;
struct fusb300 *fusb300 = ep->fusb300;
tmp = req->req.buf;
req->req.actual = req->req.length;
for (i = (req->req.length >> 2); i > 0; i--) {
data = *tmp | *(tmp + 1) << 8 |
*(tmp + 2) << 16 | *(tmp + 3) << 24;
iowrite32(data, fusb300->reg +
FUSB300_OFFSET_EPPORT(ep->epnum));
tmp += 4;
}
switch (req->req.length % 4) {
case 1:
data = *tmp;
iowrite32(data, fusb300->reg +
FUSB300_OFFSET_EPPORT(ep->epnum));
break;
case 2:
data = *tmp | *(tmp + 1) << 8;
iowrite32(data, fusb300->reg +
FUSB300_OFFSET_EPPORT(ep->epnum));
break;
case 3:
data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16;
iowrite32(data, fusb300->reg +
FUSB300_OFFSET_EPPORT(ep->epnum));
break;
default:
break;
}
do {
reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
reg &= FUSB300_IGR1_SYNF0_EMPTY_INT;
if (i)
printk(KERN_INFO"sync fifo is not empty!\n");
i++;
} while (!reg);
}
static u8 fusb300_get_epnstall(struct fusb300 *fusb300, u8 ep)
{
u8 value;
@ -980,11 +930,6 @@ static void set_address(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
} \
} while (0)
static void fusb300_ep0_complete(struct usb_ep *ep,
struct usb_request *req)
{
}
static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
{
u8 *p = (u8 *)ctrl;
@ -1029,17 +974,6 @@ static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
return ret;
}
static void fusb300_set_ep_bycnt(struct fusb300_ep *ep, u32 bycnt)
{
struct fusb300 *fusb300 = ep->fusb300;
u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
reg &= ~FUSB300_FFR_BYCNT;
reg |= bycnt & FUSB300_FFR_BYCNT;
iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
}
static void done(struct fusb300_ep *ep, struct fusb300_request *req,
int status)
{
@ -1063,8 +997,8 @@ static void done(struct fusb300_ep *ep, struct fusb300_request *req,
fusb300_set_cxdone(ep->fusb300);
}
void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep,
struct fusb300_request *req)
static void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep, dma_addr_t d,
u32 len)
{
u32 value;
u32 reg;
@ -1076,10 +1010,9 @@ void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep,
reg &= FUSB300_EPPRD0_H;
} while (reg);
iowrite32((u32) req->req.buf, ep->fusb300->reg +
FUSB300_OFFSET_EPPRD_W1(ep->epnum));
iowrite32(d, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W1(ep->epnum));
value = FUSB300_EPPRD0_BTC(req->req.length) | FUSB300_EPPRD0_H |
value = FUSB300_EPPRD0_BTC(len) | FUSB300_EPPRD0_H |
FUSB300_EPPRD0_F | FUSB300_EPPRD0_L | FUSB300_EPPRD0_I;
iowrite32(value, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W0(ep->epnum));
@ -1116,13 +1049,12 @@ static void fusb300_set_idma(struct fusb300_ep *ep,
struct fusb300_request *req)
{
dma_addr_t d;
u8 *tmp = NULL;
d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
if (dma_mapping_error(NULL, d)) {
kfree(req->req.buf);
printk(KERN_DEBUG "dma_mapping_error\n");
return;
}
dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
@ -1130,17 +1062,11 @@ static void fusb300_set_idma(struct fusb300_ep *ep,
fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
tmp = req->req.buf;
req->req.buf = (u8 *)d;
fusb300_fill_idma_prdtbl(ep, req);
fusb300_fill_idma_prdtbl(ep, d, req->req.length);
/* check idma is done */
fusb300_wait_idma_finished(ep);
req->req.buf = tmp;
if (d)
dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
}
static void in_ep_fifo_handler(struct fusb300_ep *ep)
@ -1148,14 +1074,8 @@ static void in_ep_fifo_handler(struct fusb300_ep *ep)
struct fusb300_request *req = list_entry(ep->queue.next,
struct fusb300_request, queue);
if (req->req.length) {
#if 0
fusb300_set_ep_bycnt(ep, req->req.length);
fusb300_wrfifo(ep, req);
#else
if (req->req.length)
fusb300_set_idma(ep, req);
#endif
}
done(ep, req, 0);
}
@ -1500,7 +1420,7 @@ static void init_controller(struct fusb300 *fusb300)
/*------------------------------------------------------------------------*/
static struct fusb300 *the_controller;
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int fusb300_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct fusb300 *fusb300 = the_controller;
@ -1544,9 +1464,8 @@ error:
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int fusb300_udc_stop(struct usb_gadget_driver *driver)
{
struct fusb300 *fusb300 = the_controller;
@ -1562,7 +1481,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*--------------------------------------------------------------------------*/
static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
@ -1572,12 +1490,15 @@ static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
static struct usb_gadget_ops fusb300_gadget_ops = {
.pullup = fusb300_udc_pullup,
.start = fusb300_udc_start,
.stop = fusb300_udc_stop,
};
static int __exit fusb300_remove(struct platform_device *pdev)
{
struct fusb300 *fusb300 = dev_get_drvdata(&pdev->dev);
usb_del_gadget_udc(&fusb300->gadget);
iounmap(fusb300->reg);
free_irq(platform_get_irq(pdev, 0), fusb300);
@ -1702,9 +1623,15 @@ static int __init fusb300_probe(struct platform_device *pdev)
goto clean_up3;
init_controller(fusb300);
ret = usb_add_gadget_udc(&pdev->dev, &fusb300->gadget);
if (ret)
goto err_add_udc;
dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
return 0;
err_add_udc:
fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
clean_up3:
free_irq(ires->start, fusb300);

Просмотреть файл

@ -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,
};

Просмотреть файл

@ -15,150 +15,40 @@
#ifndef __GADGET_CHIPS_H
#define __GADGET_CHIPS_H
#ifdef CONFIG_USB_GADGET_NET2280
#define gadget_is_net2280(g) !strcmp("net2280", (g)->name)
#else
#define gadget_is_net2280(g) 0
#endif
#ifdef CONFIG_USB_GADGET_AMD5536UDC
#define gadget_is_amd5536udc(g) !strcmp("amd5536udc", (g)->name)
#else
#define gadget_is_amd5536udc(g) 0
#endif
#ifdef CONFIG_USB_GADGET_DUMMY_HCD
#define gadget_is_dummy(g) !strcmp("dummy_udc", (g)->name)
#else
#define gadget_is_dummy(g) 0
#endif
#ifdef CONFIG_USB_GADGET_PXA25X
#define gadget_is_pxa(g) !strcmp("pxa25x_udc", (g)->name)
#else
#define gadget_is_pxa(g) 0
#endif
#ifdef CONFIG_USB_GADGET_GOKU
#define gadget_is_goku(g) !strcmp("goku_udc", (g)->name)
#else
#define gadget_is_goku(g) 0
#endif
#ifdef CONFIG_USB_GADGET_OMAP
#define gadget_is_omap(g) !strcmp("omap_udc", (g)->name)
#else
#define gadget_is_omap(g) 0
#endif
/* various unstable versions available */
#ifdef CONFIG_USB_GADGET_PXA27X
#define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name)
#else
#define gadget_is_pxa27x(g) 0
#endif
#ifdef CONFIG_USB_GADGET_ATMEL_USBA
#define gadget_is_atmel_usba(g) !strcmp("atmel_usba_udc", (g)->name)
#else
#define gadget_is_atmel_usba(g) 0
#endif
#ifdef CONFIG_USB_GADGET_S3C2410
#define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name)
#else
#define gadget_is_s3c2410(g) 0
#endif
#ifdef CONFIG_USB_GADGET_AT91
#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
#else
#define gadget_is_at91(g) 0
#endif
#ifdef CONFIG_USB_GADGET_IMX
#define gadget_is_imx(g) !strcmp("imx_udc", (g)->name)
#else
#define gadget_is_imx(g) 0
#endif
#ifdef CONFIG_USB_GADGET_FSL_USB2
#define gadget_is_fsl_usb2(g) !strcmp("fsl-usb2-udc", (g)->name)
#else
#define gadget_is_fsl_usb2(g) 0
#endif
/* Mentor high speed "dual role" controller, in peripheral role */
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
#define gadget_is_musbhdrc(g) !strcmp("musb-hdrc", (g)->name)
#else
#define gadget_is_musbhdrc(g) 0
#endif
#ifdef CONFIG_USB_GADGET_LANGWELL
#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name))
#else
#define gadget_is_langwell(g) 0
#endif
#ifdef CONFIG_USB_GADGET_M66592
#define gadget_is_m66592(g) !strcmp("m66592_udc", (g)->name)
#else
#define gadget_is_m66592(g) 0
#endif
/* Freescale CPM/QE UDC SUPPORT */
#ifdef CONFIG_USB_GADGET_FSL_QE
#define gadget_is_fsl_qe(g) !strcmp("fsl_qe_udc", (g)->name)
#else
#define gadget_is_fsl_qe(g) 0
#endif
#ifdef CONFIG_USB_GADGET_CI13XXX_PCI
#define gadget_is_ci13xxx_pci(g) (!strcmp("ci13xxx_pci", (g)->name))
#else
#define gadget_is_ci13xxx_pci(g) 0
#endif
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
// ...
#ifdef CONFIG_USB_GADGET_R8A66597
#define gadget_is_r8a66597(g) !strcmp("r8a66597_udc", (g)->name)
#else
#define gadget_is_r8a66597(g) 0
#endif
#ifdef CONFIG_USB_S3C_HSOTG
#define gadget_is_s3c_hsotg(g) (!strcmp("s3c-hsotg", (g)->name))
#else
#define gadget_is_s3c_hsotg(g) 0
#endif
#ifdef CONFIG_USB_S3C_HSUDC
#define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name))
#else
#define gadget_is_s3c_hsudc(g) 0
#endif
#ifdef CONFIG_USB_GADGET_EG20T
#define gadget_is_pch(g) (!strcmp("pch_udc", (g)->name))
#else
#define gadget_is_pch(g) 0
#endif
#ifdef CONFIG_USB_GADGET_CI13XXX_MSM
/*
* NOTICE: the entries below are alphabetical and should be kept
* that way.
*
* Always be sure to add new entries to the correct position or
* accept the bashing later.
*
* If you have forgotten the alphabetical order let VIM/EMACS
* do that for you.
*/
#define gadget_is_amd5536udc(g) (!strcmp("amd5536udc", (g)->name))
#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name))
#define gadget_is_atmel_usba(g) (!strcmp("atmel_usba_udc", (g)->name))
#define gadget_is_ci13xxx_msm(g) (!strcmp("ci13xxx_msm", (g)->name))
#else
#define gadget_is_ci13xxx_msm(g) 0
#endif
#ifdef CONFIG_USB_GADGET_RENESAS_USBHS
#define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name))
#else
#define gadget_is_renesas_usbhs(g) 0
#endif
#define gadget_is_ci13xxx_pci(g) (!strcmp("ci13xxx_pci", (g)->name))
#define gadget_is_dummy(g) (!strcmp("dummy_udc", (g)->name))
#define gadget_is_fsl_qe(g) (!strcmp("fsl_qe_udc", (g)->name))
#define gadget_is_fsl_usb2(g) (!strcmp("fsl-usb2-udc", (g)->name))
#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name))
#define gadget_is_imx(g) (!strcmp("imx_udc", (g)->name))
#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name))
#define gadget_is_m66592(g) (!strcmp("m66592_udc", (g)->name))
#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
#define gadget_is_net2272(g) (!strcmp("net2272", (g)->name))
#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name))
#define gadget_is_omap(g) (!strcmp("omap_udc", (g)->name))
#define gadget_is_pch(g) (!strcmp("pch_udc", (g)->name))
#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name))
#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name))
#define gadget_is_r8a66597(g) (!strcmp("r8a66597_udc", (g)->name))
#define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name))
#define gadget_is_s3c2410(g) (!strcmp("s3c2410_udc", (g)->name))
#define gadget_is_s3c_hsotg(g) (!strcmp("s3c-hsotg", (g)->name))
#define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name))
/**
* usb_gadget_controller_number - support bcdDevice id convention
@ -223,6 +113,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x29;
else if (gadget_is_s3c_hsudc(gadget))
return 0x30;
else if (gadget_is_net2272(gadget))
return 0x31;
return -ENOENT;
}

Просмотреть файл

@ -537,14 +537,16 @@ static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags)
struct usb_ep *ep;
unsigned i;
err = usb_ep_enable(dev->in_ep, &bulk_in_desc);
dev->in_ep->desc = &bulk_in_desc;
err = usb_ep_enable(dev->in_ep);
if (err) {
ERROR(dev, "can't start %s: %d\n", dev->in_ep->name, err);
goto fail;
}
dev->in_ep->driver_data = dev;
err = usb_ep_enable(dev->out_ep, &bulk_out_desc);
dev->out_ep->desc = &bulk_out_desc;
err = usb_ep_enable(dev->out_ep);
if (err) {
ERROR(dev, "can't start %s: %d\n", dev->out_ep->name, err);
goto fail;
@ -693,6 +695,7 @@ static int gmidi_setup(struct usb_gadget *gadget,
switch (w_value >> 8) {
case USB_DT_DEVICE:
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
value = min(w_length, (u16) sizeof(device_desc));
memcpy(req->buf, &device_desc, value);
break;
@ -1247,8 +1250,6 @@ autoconf_fail:
dev->req->complete = gmidi_setup_complete;
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
gadget->ep0->driver_data = dev;
INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);

Просмотреть файл

@ -996,8 +996,14 @@ static int goku_get_frame(struct usb_gadget *_gadget)
return -EOPNOTSUPP;
}
static int goku_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int goku_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops goku_ops = {
.get_frame = goku_get_frame,
.start = goku_start,
.stop = goku_stop,
// no remote wakeup
// not selfpowered
};
@ -1344,7 +1350,7 @@ static struct goku_udc *the_controller;
* disconnect is reported. then a host may connect again, or
* the driver might get unbound.
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int goku_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct goku_udc *dev = the_controller;
@ -1382,7 +1388,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
DBG(dev, "registered gadget driver '%s'\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
static void
stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
@ -1408,7 +1413,7 @@ stop_activity(struct goku_udc *dev, struct usb_gadget_driver *driver)
udc_enable(dev);
}
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int goku_stop(struct usb_gadget_driver *driver)
{
struct goku_udc *dev = the_controller;
unsigned long flags;
@ -1429,8 +1434,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------*/
@ -1730,6 +1733,8 @@ static void goku_remove(struct pci_dev *pdev)
DBG(dev, "%s\n", __func__);
usb_del_gadget_udc(&dev->gadget);
BUG_ON(dev->driver);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
@ -1854,6 +1859,10 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err;
}
dev->registered = 1;
retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
if (retval)
goto err;
return 0;
err:

Просмотреть файл

@ -255,6 +255,7 @@ static struct usb_composite_driver hidg_driver = {
.name = "g_hid",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = __exit_p(hid_unbind),
};

Просмотреть файл

@ -1237,9 +1237,14 @@ irq_handler_t intr_handler(int i)
*******************************************************************************
*/
static int imx_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int imx_udc_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops imx_udc_ops = {
.get_frame = imx_udc_get_frame,
.wakeup = imx_udc_wakeup,
.start = imx_udc_start,
.stop = imx_udc_stop,
};
static struct imx_udc_struct controller = {
@ -1324,7 +1329,7 @@ static struct imx_udc_struct controller = {
* USB gadget driver functions
*******************************************************************************
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int imx_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct imx_udc_struct *imx_usb = &controller;
@ -1368,9 +1373,8 @@ fail:
imx_usb->gadget.dev.driver = NULL;
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int imx_udc_stop(struct usb_gadget_driver *driver)
{
struct imx_udc_struct *imx_usb = &controller;
@ -1394,7 +1398,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*******************************************************************************
* Module functions
@ -1504,8 +1507,14 @@ static int __init imx_udc_probe(struct platform_device *pdev)
imx_usb->timer.function = handle_config;
imx_usb->timer.data = (unsigned long)imx_usb;
return 0;
ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
if (ret)
goto fail4;
return 0;
fail4:
for (i = 0; i < IMX_USB_NB_EP + 1; i++)
free_irq(imx_usb->usbd_int[i], imx_usb);
fail3:
clk_put(clk);
clk_disable(clk);
@ -1525,6 +1534,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
struct imxusb_platform_data *pdata = pdev->dev.platform_data;
int i;
usb_del_gadget_udc(&imx_usb->gadget);
imx_udc_disable(imx_usb);
del_timer(&imx_usb->timer);

Просмотреть файл

@ -832,14 +832,16 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
switch (data->dev->gadget->speed) {
case USB_SPEED_LOW:
case USB_SPEED_FULL:
value = usb_ep_enable (ep, &data->desc);
ep->desc = &data->desc;
value = usb_ep_enable(ep);
if (value == 0)
data->state = STATE_EP_ENABLED;
break;
#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_SPEED_HIGH:
/* fails if caller didn't provide that descriptor... */
value = usb_ep_enable (ep, &data->hs_desc);
ep->desc = &data->hs_desc;
value = usb_ep_enable(ep);
if (value == 0)
data->state = STATE_EP_ENABLED;
break;
@ -1345,7 +1347,7 @@ static void make_qualifier (struct dev_data *dev)
qual.bDeviceProtocol = desc->bDeviceProtocol;
/* assumes ep0 uses the same value for both speeds ... */
qual.bMaxPacketSize0 = desc->bMaxPacketSize0;
qual.bMaxPacketSize0 = dev->gadget->ep0->maxpacket;
qual.bNumConfigurations = 1;
qual.bRESERVED = 0;
@ -1402,7 +1404,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
}
dev->state = STATE_DEV_CONNECTED;
dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
INFO (dev, "connected\n");
event = next_event (dev, GADGETFS_CONNECT);
@ -1430,6 +1431,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_DT_DEVICE:
value = min (w_length, (u16) sizeof *dev->dev);
dev->dev->bMaxPacketSize0 = dev->gadget->ep0->maxpacket;
req->buf = dev->dev;
break;
#ifdef CONFIG_USB_GADGET_DUALSPEED
@ -1710,7 +1712,6 @@ gadgetfs_bind (struct usb_gadget *gadget)
set_gadget_data (gadget, dev);
dev->gadget = gadget;
gadget->ep0->driver_data = dev;
dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
/* preallocate control response and buffer */
dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);

Просмотреть файл

@ -593,8 +593,8 @@ static int queue_dtd(struct langwell_ep *ep, struct langwell_request *req)
/* ep0 */
dev_vdbg(&dev->pdev->dev, "%s-%s\n", ep->name, DIR_STRING(ep));
dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%08x\n",
i, (u32)&(dev->ep_dqh[i]));
dev_vdbg(&dev->pdev->dev, "ep_dqh[%d] addr: 0x%p\n",
i, &(dev->ep_dqh[i]));
bit_mask = is_in(ep) ?
(1 << (ep->ep_num + 16)) : (1 << (ep->ep_num));
@ -1321,7 +1321,9 @@ static int langwell_pullup(struct usb_gadget *_gadget, int is_on)
return 0;
}
static int langwell_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int langwell_stop(struct usb_gadget_driver *driver);
/* device controller usb_gadget_ops structure */
static const struct usb_gadget_ops langwell_ops = {
@ -1342,6 +1344,9 @@ static const struct usb_gadget_ops langwell_ops = {
/* D+ pullup, software-controlled connect/disconnect to USB host */
.pullup = langwell_pullup,
.start = langwell_start,
.stop = langwell_stop,
};
@ -1852,7 +1857,7 @@ static DEVICE_ATTR(remote_wakeup, S_IWUSR, NULL, store_remote_wakeup);
* the driver might get unbound.
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int langwell_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct langwell_udc *dev = the_controller;
@ -1914,11 +1919,9 @@ err_unbind:
dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
/* unregister gadget driver */
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int langwell_stop(struct usb_gadget_driver *driver)
{
struct langwell_udc *dev = the_controller;
unsigned long flags;
@ -1965,8 +1968,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------*/
@ -3270,7 +3271,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
/* allocate device dQH memory */
size = dev->ep_max * sizeof(struct langwell_dqh);
dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size);
if (size < DQH_ALIGNMENT)
size = DQH_ALIGNMENT;
else if ((size % DQH_ALIGNMENT) != 0) {
@ -3285,7 +3286,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
goto error;
}
dev->ep_dqh_size = size;
dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size);
/* initialize ep0 status request structure */
dev->status_req = kzalloc(sizeof(struct langwell_request), GFP_KERNEL);
@ -3373,6 +3374,10 @@ static int langwell_udc_probe(struct pci_dev *pdev,
if (retval)
goto error;
retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
if (retval)
goto error;
retval = device_create_file(&pdev->dev, &dev_attr_langwell_udc);
if (retval)
goto error;
@ -3403,6 +3408,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
usb_del_gadget_udc(&dev->gadget);
/* disable interrupt and set controller to stop state */
langwell_udc_stop(dev);
@ -3464,7 +3470,7 @@ static int langwell_udc_resume(struct pci_dev *pdev)
/* allocate device dQH memory */
size = dev->ep_max * sizeof(struct langwell_dqh);
dev_vdbg(&dev->pdev->dev, "orig size = %d\n", size);
dev_vdbg(&dev->pdev->dev, "orig size = %zd\n", size);
if (size < DQH_ALIGNMENT)
size = DQH_ALIGNMENT;
else if ((size % DQH_ALIGNMENT) != 0) {
@ -3478,7 +3484,7 @@ static int langwell_udc_resume(struct pci_dev *pdev)
return -ENOMEM;
}
dev->ep_dqh_size = size;
dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %d\n", dev->ep_dqh_size);
dev_vdbg(&dev->pdev->dev, "ep_dqh_size = %zd\n", dev->ep_dqh_size);
/* create dTD dma_pool resource */
dev->dtd_pool = dma_pool_create("langwell_dtd",

Просмотреть файл

@ -3,7 +3,7 @@
*
* Copyright (C) 2006-2007 Renesas Solutions Corp.
*
* Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
* Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -691,6 +691,7 @@ static void init_controller(struct m66592 *m66592)
static void disable_controller(struct m66592 *m66592)
{
m66592_bclr(m66592, M66592_UTST, M66592_TESTMODE);
if (!m66592->pdata->on_chip) {
m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
udelay(1);
@ -780,7 +781,7 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
/* write fifo */
if (req->req.buf) {
if (size > 0)
m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
m66592_write_fifo(m66592, ep, buf, size);
if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
}
@ -826,7 +827,7 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
/* write fifo */
if (req->req.buf) {
m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
m66592_write_fifo(m66592, ep, buf, size);
if ((size == 0)
|| ((size % ep->ep.maxpacket) != 0)
|| ((bufsize != ep->ep.maxpacket)
@ -1048,10 +1049,30 @@ static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
{
u16 tmp;
int timeout = 3000;
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
control_end(m66592, 1);
switch (le16_to_cpu(ctrl->wValue)) {
case USB_DEVICE_TEST_MODE:
control_end(m66592, 1);
/* Wait for the completion of status stage */
do {
tmp = m66592_read(m66592, M66592_INTSTS0) &
M66592_CTSQ;
udelay(1);
} while (tmp != M66592_CS_IDST || timeout-- > 0);
if (tmp == M66592_CS_IDST)
m66592_bset(m66592,
le16_to_cpu(ctrl->wIndex >> 8),
M66592_TESTMODE);
break;
default:
pipe_stall(m66592, 0);
break;
}
break;
case USB_RECIP_INTERFACE:
control_end(m66592, 1);
@ -1454,7 +1475,7 @@ static struct usb_ep_ops m66592_ep_ops = {
/*-------------------------------------------------------------------------*/
static struct m66592 *the_controller;
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int m66592_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct m66592 *m66592 = the_controller;
@ -1506,9 +1527,8 @@ error:
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int m66592_stop(struct usb_gadget_driver *driver)
{
struct m66592 *m66592 = the_controller;
unsigned long flags;
@ -1533,7 +1553,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
m66592->driver = NULL;
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------*/
static int m66592_get_frame(struct usb_gadget *_gadget)
@ -1542,14 +1561,34 @@ static int m66592_get_frame(struct usb_gadget *_gadget)
return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
}
static int m66592_pullup(struct usb_gadget *gadget, int is_on)
{
struct m66592 *m66592 = gadget_to_m66592(gadget);
unsigned long flags;
spin_lock_irqsave(&m66592->lock, flags);
if (is_on)
m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
else
m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
spin_unlock_irqrestore(&m66592->lock, flags);
return 0;
}
static struct usb_gadget_ops m66592_gadget_ops = {
.get_frame = m66592_get_frame,
.start = m66592_start,
.stop = m66592_stop,
.pullup = m66592_pullup,
};
static int __exit m66592_remove(struct platform_device *pdev)
{
struct m66592 *m66592 = dev_get_drvdata(&pdev->dev);
usb_del_gadget_udc(&m66592->gadget);
del_timer_sync(&m66592->timer);
iounmap(m66592->reg);
free_irq(platform_get_irq(pdev, 0), m66592);
@ -1691,9 +1730,16 @@ static int __init m66592_probe(struct platform_device *pdev)
init_controller(m66592);
ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
if (ret)
goto err_add_udc;
dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
return 0;
err_add_udc:
m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
clean_up3:
#ifdef CONFIG_HAVE_CLK
if (m66592->pdata->on_chip) {

Просмотреть файл

@ -3,7 +3,7 @@
*
* Copyright (C) 2006-2007 Renesas Solutions Corp.
*
* Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
* Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -561,11 +561,26 @@ static inline void m66592_write(struct m66592 *m66592, u16 val,
iowrite16(val, m66592->reg + offset);
}
static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
unsigned long offset)
{
u16 tmp;
tmp = m66592_read(m66592, offset);
tmp = tmp & (~pat);
tmp = tmp | val;
m66592_write(m66592, tmp, offset);
}
#define m66592_bclr(m66592, val, offset) \
m66592_mdfy(m66592, 0, val, offset)
#define m66592_bset(m66592, val, offset) \
m66592_mdfy(m66592, val, 0, offset)
static inline void m66592_write_fifo(struct m66592 *m66592,
unsigned long offset,
struct m66592_ep *ep,
void *buf, unsigned long len)
{
void __iomem *fifoaddr = m66592->reg + offset;
void __iomem *fifoaddr = m66592->reg + ep->fifoaddr;
if (m66592->pdata->on_chip) {
unsigned long count;
@ -591,26 +606,15 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
iowrite16_rep(fifoaddr, buf, len);
if (odd) {
unsigned char *p = buf + len*2;
if (m66592->pdata->wr0_shorted_to_wr1)
m66592_bclr(m66592, M66592_MBW_16, ep->fifosel);
iowrite8(*p, fifoaddr);
if (m66592->pdata->wr0_shorted_to_wr1)
m66592_bset(m66592, M66592_MBW_16, ep->fifosel);
}
}
}
static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
unsigned long offset)
{
u16 tmp;
tmp = m66592_read(m66592, offset);
tmp = tmp & (~pat);
tmp = tmp | val;
m66592_write(m66592, tmp, offset);
}
#define m66592_bclr(m66592, val, offset) \
m66592_mdfy(m66592, 0, val, offset)
#define m66592_bset(m66592, val, offset) \
m66592_mdfy(m66592, val, 0, offset)
#endif /* ifndef __M66592_UDC_H__ */

Просмотреть файл

@ -169,6 +169,7 @@ static struct usb_composite_driver msg_driver = {
.name = "g_mass_storage",
.dev = &msg_device_desc,
.iProduct = DRIVER_DESC,
.max_speed = USB_SPEED_HIGH,
.needs_serial = 1,
};

Просмотреть файл

@ -351,6 +351,7 @@ static struct usb_composite_driver multi_driver = {
.name = "g_multi",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = __exit_p(multi_unbind),
.iProduct = DRIVER_DESC,
.needs_serial = 1,

Просмотреть файл

@ -1128,6 +1128,9 @@ static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
static int mv_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int mv_udc_stop(struct usb_gadget_driver *driver);
/* device controller usb_gadget_ops structure */
static const struct usb_gadget_ops mv_ops = {
@ -1139,6 +1142,8 @@ static const struct usb_gadget_ops mv_ops = {
/* D+ pullup, software-controlled connect/disconnect to USB host */
.pullup = mv_udc_pullup,
.start = mv_udc_start,
.stop = mv_udc_stop,
};
static void mv_udc_testmode(struct mv_udc *udc, u16 index, bool enter)
@ -1230,7 +1235,7 @@ static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
}
}
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int mv_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct mv_udc *udc = the_controller;
@ -1270,9 +1275,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
return 0;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int mv_udc_stop(struct usb_gadget_driver *driver)
{
struct mv_udc *udc = the_controller;
unsigned long flags;
@ -1296,7 +1300,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
static int
udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
@ -1880,9 +1883,10 @@ static void gadget_release(struct device *_dev)
static int mv_udc_remove(struct platform_device *dev)
{
struct mv_udc *udc = the_controller;
DECLARE_COMPLETION(done);
usb_del_gadget_udc(&udc->gadget);
udc->done = &done;
/* free memory allocated in probe */
@ -2074,11 +2078,12 @@ int mv_udc_probe(struct platform_device *dev)
the_controller = udc;
goto out;
retval = usb_add_gadget_udc(&dev->dev, &udc->gadget);
if (!retval)
return retval;
error:
if (udc)
mv_udc_remove(udc->dev);
out:
return retval;
}
@ -2126,7 +2131,7 @@ static struct platform_driver udc_driver = {
#endif
},
};
MODULE_ALIAS("platform:pxa-u2o");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");

Просмотреть файл

@ -228,6 +228,7 @@ static struct usb_composite_driver ncm_driver = {
.name = "g_ncm",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = __exit_p(gncm_unbind),
};

2752
drivers/usb/gadget/net2272.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,601 @@
/*
* PLX NET2272 high/full speed USB device controller
*
* Copyright (C) 2005-2006 PLX Technology, Inc.
* Copyright (C) 2006-2011 Analog Devices, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __NET2272_H__
#define __NET2272_H__
/* Main Registers */
#define REGADDRPTR 0x00
#define REGDATA 0x01
#define IRQSTAT0 0x02
#define ENDPOINT_0_INTERRUPT 0
#define ENDPOINT_A_INTERRUPT 1
#define ENDPOINT_B_INTERRUPT 2
#define ENDPOINT_C_INTERRUPT 3
#define VIRTUALIZED_ENDPOINT_INTERRUPT 4
#define SETUP_PACKET_INTERRUPT 5
#define DMA_DONE_INTERRUPT 6
#define SOF_INTERRUPT 7
#define IRQSTAT1 0x03
#define CONTROL_STATUS_INTERRUPT 1
#define VBUS_INTERRUPT 2
#define SUSPEND_REQUEST_INTERRUPT 3
#define SUSPEND_REQUEST_CHANGE_INTERRUPT 4
#define RESUME_INTERRUPT 5
#define ROOT_PORT_RESET_INTERRUPT 6
#define RESET_STATUS 7
#define PAGESEL 0x04
#define DMAREQ 0x1c
#define DMA_ENDPOINT_SELECT 0
#define DREQ_POLARITY 1
#define DACK_POLARITY 2
#define EOT_POLARITY 3
#define DMA_CONTROL_DACK 4
#define DMA_REQUEST_ENABLE 5
#define DMA_REQUEST 6
#define DMA_BUFFER_VALID 7
#define SCRATCH 0x1d
#define IRQENB0 0x20
#define ENDPOINT_0_INTERRUPT_ENABLE 0
#define ENDPOINT_A_INTERRUPT_ENABLE 1
#define ENDPOINT_B_INTERRUPT_ENABLE 2
#define ENDPOINT_C_INTERRUPT_ENABLE 3
#define VIRTUALIZED_ENDPOINT_INTERRUPT_ENABLE 4
#define SETUP_PACKET_INTERRUPT_ENABLE 5
#define DMA_DONE_INTERRUPT_ENABLE 6
#define SOF_INTERRUPT_ENABLE 7
#define IRQENB1 0x21
#define VBUS_INTERRUPT_ENABLE 2
#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 4
#define RESUME_INTERRUPT_ENABLE 5
#define ROOT_PORT_RESET_INTERRUPT_ENABLE 6
#define LOCCTL 0x22
#define DATA_WIDTH 0
#define LOCAL_CLOCK_OUTPUT 1
#define LOCAL_CLOCK_OUTPUT_OFF 0
#define LOCAL_CLOCK_OUTPUT_3_75MHZ 1
#define LOCAL_CLOCK_OUTPUT_7_5MHZ 2
#define LOCAL_CLOCK_OUTPUT_15MHZ 3
#define LOCAL_CLOCK_OUTPUT_30MHZ 4
#define LOCAL_CLOCK_OUTPUT_60MHZ 5
#define DMA_SPLIT_BUS_MODE 4
#define BYTE_SWAP 5
#define BUFFER_CONFIGURATION 6
#define BUFFER_CONFIGURATION_EPA512_EPB512 0
#define BUFFER_CONFIGURATION_EPA1024_EPB512 1
#define BUFFER_CONFIGURATION_EPA1024_EPB1024 2
#define BUFFER_CONFIGURATION_EPA1024DB 3
#define CHIPREV_LEGACY 0x23
#define NET2270_LEGACY_REV 0x40
#define LOCCTL1 0x24
#define DMA_MODE 0
#define SLOW_DREQ 0
#define FAST_DREQ 1
#define BURST_MODE 2
#define DMA_DACK_ENABLE 2
#define CHIPREV_2272 0x25
#define CHIPREV_NET2272_R1 0x10
#define CHIPREV_NET2272_R1A 0x11
/* USB Registers */
#define USBCTL0 0x18
#define IO_WAKEUP_ENABLE 1
#define USB_DETECT_ENABLE 3
#define USB_ROOT_PORT_WAKEUP_ENABLE 5
#define USBCTL1 0x19
#define VBUS_PIN 0
#define USB_FULL_SPEED 1
#define USB_HIGH_SPEED 2
#define GENERATE_RESUME 3
#define VIRTUAL_ENDPOINT_ENABLE 4
#define FRAME0 0x1a
#define FRAME1 0x1b
#define OURADDR 0x30
#define FORCE_IMMEDIATE 7
#define USBDIAG 0x31
#define FORCE_TRANSMIT_CRC_ERROR 0
#define PREVENT_TRANSMIT_BIT_STUFF 1
#define FORCE_RECEIVE_ERROR 2
#define FAST_TIMES 4
#define USBTEST 0x32
#define TEST_MODE_SELECT 0
#define NORMAL_OPERATION 0
#define TEST_J 1
#define TEST_K 2
#define TEST_SE0_NAK 3
#define TEST_PACKET 4
#define TEST_FORCE_ENABLE 5
#define XCVRDIAG 0x33
#define FORCE_FULL_SPEED 2
#define FORCE_HIGH_SPEED 3
#define OPMODE 4
#define NORMAL_OPERATION 0
#define NON_DRIVING 1
#define DISABLE_BITSTUFF_AND_NRZI_ENCODE 2
#define LINESTATE 6
#define SE0_STATE 0
#define J_STATE 1
#define K_STATE 2
#define SE1_STATE 3
#define VIRTOUT0 0x34
#define VIRTOUT1 0x35
#define VIRTIN0 0x36
#define VIRTIN1 0x37
#define SETUP0 0x40
#define SETUP1 0x41
#define SETUP2 0x42
#define SETUP3 0x43
#define SETUP4 0x44
#define SETUP5 0x45
#define SETUP6 0x46
#define SETUP7 0x47
/* Endpoint Registers (Paged via PAGESEL) */
#define EP_DATA 0x05
#define EP_STAT0 0x06
#define DATA_IN_TOKEN_INTERRUPT 0
#define DATA_OUT_TOKEN_INTERRUPT 1
#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
#define DATA_PACKET_RECEIVED_INTERRUPT 3
#define SHORT_PACKET_TRANSFERRED_INTERRUPT 4
#define NAK_OUT_PACKETS 5
#define BUFFER_EMPTY 6
#define BUFFER_FULL 7
#define EP_STAT1 0x07
#define TIMEOUT 0
#define USB_OUT_ACK_SENT 1
#define USB_OUT_NAK_SENT 2
#define USB_IN_ACK_RCVD 3
#define USB_IN_NAK_SENT 4
#define USB_STALL_SENT 5
#define LOCAL_OUT_ZLP 6
#define BUFFER_FLUSH 7
#define EP_TRANSFER0 0x08
#define EP_TRANSFER1 0x09
#define EP_TRANSFER2 0x0a
#define EP_IRQENB 0x0b
#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
#define DATA_OUT_TOKEN_INTERRUPT_ENABLE 1
#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 4
#define EP_AVAIL0 0x0c
#define EP_AVAIL1 0x0d
#define EP_RSPCLR 0x0e
#define EP_RSPSET 0x0f
#define ENDPOINT_HALT 0
#define ENDPOINT_TOGGLE 1
#define NAK_OUT_PACKETS_MODE 2
#define CONTROL_STATUS_PHASE_HANDSHAKE 3
#define INTERRUPT_MODE 4
#define AUTOVALIDATE 5
#define HIDE_STATUS_PHASE 6
#define ALT_NAK_OUT_PACKETS 7
#define EP_MAXPKT0 0x28
#define EP_MAXPKT1 0x29
#define ADDITIONAL_TRANSACTION_OPPORTUNITIES 3
#define NONE_ADDITIONAL_TRANSACTION 0
#define ONE_ADDITIONAL_TRANSACTION 1
#define TWO_ADDITIONAL_TRANSACTION 2
#define EP_CFG 0x2a
#define ENDPOINT_NUMBER 0
#define ENDPOINT_DIRECTION 4
#define ENDPOINT_TYPE 5
#define ENDPOINT_ENABLE 7
#define EP_HBW 0x2b
#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 0
#define DATA0_PID 0
#define DATA1_PID 1
#define DATA2_PID 2
#define MDATA_PID 3
#define EP_BUFF_STATES 0x2c
#define BUFFER_A_STATE 0
#define BUFFER_B_STATE 2
#define BUFF_FREE 0
#define BUFF_VALID 1
#define BUFF_LCL 2
#define BUFF_USB 3
/*---------------------------------------------------------------------------*/
#define PCI_DEVICE_ID_RDK1 0x9054
/* PCI-RDK EPLD Registers */
#define RDK_EPLD_IO_REGISTER1 0x00000000
#define RDK_EPLD_USB_RESET 0
#define RDK_EPLD_USB_POWERDOWN 1
#define RDK_EPLD_USB_WAKEUP 2
#define RDK_EPLD_USB_EOT 3
#define RDK_EPLD_DPPULL 4
#define RDK_EPLD_IO_REGISTER2 0x00000004
#define RDK_EPLD_BUSWIDTH 0
#define RDK_EPLD_USER 2
#define RDK_EPLD_RESET_INTERRUPT_ENABLE 3
#define RDK_EPLD_DMA_TIMEOUT_ENABLE 4
#define RDK_EPLD_STATUS_REGISTER 0x00000008
#define RDK_EPLD_USB_LRESET 0
#define RDK_EPLD_REVISION_REGISTER 0x0000000c
/* PCI-RDK PLX 9054 Registers */
#define INTCSR 0x68
#define PCI_INTERRUPT_ENABLE 8
#define LOCAL_INTERRUPT_INPUT_ENABLE 11
#define LOCAL_INPUT_INTERRUPT_ACTIVE 15
#define LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE 18
#define LOCAL_DMA_CHANNEL_1_INTERRUPT_ENABLE 19
#define DMA_CHANNEL_0_INTERRUPT_ACTIVE 21
#define DMA_CHANNEL_1_INTERRUPT_ACTIVE 22
#define CNTRL 0x6C
#define RELOAD_CONFIGURATION_REGISTERS 29
#define PCI_ADAPTER_SOFTWARE_RESET 30
#define DMAMODE0 0x80
#define LOCAL_BUS_WIDTH 0
#define INTERNAL_WAIT_STATES 2
#define TA_READY_INPUT_ENABLE 6
#define LOCAL_BURST_ENABLE 8
#define SCATTER_GATHER_MODE 9
#define DONE_INTERRUPT_ENABLE 10
#define LOCAL_ADDRESSING_MODE 11
#define DEMAND_MODE 12
#define DMA_EOT_ENABLE 14
#define FAST_SLOW_TERMINATE_MODE_SELECT 15
#define DMA_CHANNEL_INTERRUPT_SELECT 17
#define DMAPADR0 0x84
#define DMALADR0 0x88
#define DMASIZ0 0x8c
#define DMADPR0 0x90
#define DESCRIPTOR_LOCATION 0
#define END_OF_CHAIN 1
#define INTERRUPT_AFTER_TERMINAL_COUNT 2
#define DIRECTION_OF_TRANSFER 3
#define DMACSR0 0xa8
#define CHANNEL_ENABLE 0
#define CHANNEL_START 1
#define CHANNEL_ABORT 2
#define CHANNEL_CLEAR_INTERRUPT 3
#define CHANNEL_DONE 4
#define DMATHR 0xb0
#define LBRD1 0xf8
#define MEMORY_SPACE_LOCAL_BUS_WIDTH 0
#define W8_BIT 0
#define W16_BIT 1
/* Special OR'ing of INTCSR bits */
#define LOCAL_INTERRUPT_TEST \
((1 << LOCAL_INPUT_INTERRUPT_ACTIVE) | \
(1 << LOCAL_INTERRUPT_INPUT_ENABLE))
#define DMA_CHANNEL_0_TEST \
((1 << DMA_CHANNEL_0_INTERRUPT_ACTIVE) | \
(1 << LOCAL_DMA_CHANNEL_0_INTERRUPT_ENABLE))
#define DMA_CHANNEL_1_TEST \
((1 << DMA_CHANNEL_1_INTERRUPT_ACTIVE) | \
(1 << LOCAL_DMA_CHANNEL_1_INTERRUPT_ENABLE))
/* EPLD Registers */
#define RDK_EPLD_IO_REGISTER1 0x00000000
#define RDK_EPLD_USB_RESET 0
#define RDK_EPLD_USB_POWERDOWN 1
#define RDK_EPLD_USB_WAKEUP 2
#define RDK_EPLD_USB_EOT 3
#define RDK_EPLD_DPPULL 4
#define RDK_EPLD_IO_REGISTER2 0x00000004
#define RDK_EPLD_BUSWIDTH 0
#define RDK_EPLD_USER 2
#define RDK_EPLD_RESET_INTERRUPT_ENABLE 3
#define RDK_EPLD_DMA_TIMEOUT_ENABLE 4
#define RDK_EPLD_STATUS_REGISTER 0x00000008
#define RDK_EPLD_USB_LRESET 0
#define RDK_EPLD_REVISION_REGISTER 0x0000000c
#define EPLD_IO_CONTROL_REGISTER 0x400
#define NET2272_RESET 0
#define BUSWIDTH 1
#define MPX_MODE 3
#define USER 4
#define DMA_TIMEOUT_ENABLE 5
#define DMA_CTL_DACK 6
#define EPLD_DMA_ENABLE 7
#define EPLD_DMA_CONTROL_REGISTER 0x800
#define SPLIT_DMA_MODE 0
#define SPLIT_DMA_DIRECTION 1
#define SPLIT_DMA_ENABLE 2
#define SPLIT_DMA_INTERRUPT_ENABLE 3
#define SPLIT_DMA_INTERRUPT 4
#define EPLD_DMA_MODE 5
#define EPLD_DMA_CONTROLLER_ENABLE 7
#define SPLIT_DMA_ADDRESS_LOW 0xc00
#define SPLIT_DMA_ADDRESS_HIGH 0x1000
#define SPLIT_DMA_BYTE_COUNT_LOW 0x1400
#define SPLIT_DMA_BYTE_COUNT_HIGH 0x1800
#define EPLD_REVISION_REGISTER 0x1c00
#define SPLIT_DMA_RAM 0x4000
#define DMA_RAM_SIZE 0x1000
/*---------------------------------------------------------------------------*/
#define PCI_DEVICE_ID_RDK2 0x3272
/* PCI-RDK version 2 registers */
/* Main Control Registers */
#define RDK2_IRQENB 0x00
#define RDK2_IRQSTAT 0x04
#define PB7 23
#define PB6 22
#define PB5 21
#define PB4 20
#define PB3 19
#define PB2 18
#define PB1 17
#define PB0 16
#define GP3 23
#define GP2 23
#define GP1 23
#define GP0 23
#define DMA_RETRY_ABORT 6
#define DMA_PAUSE_DONE 5
#define DMA_ABORT_DONE 4
#define DMA_OUT_FIFO_TRANSFER_DONE 3
#define DMA_LOCAL_DONE 2
#define DMA_PCI_DONE 1
#define NET2272_PCI_IRQ 0
#define RDK2_LOCCTLRDK 0x08
#define CHIP_RESET 3
#define SPLIT_DMA 2
#define MULTIPLEX_MODE 1
#define BUS_WIDTH 0
#define RDK2_GPIOCTL 0x10
#define GP3_OUT_ENABLE 7
#define GP2_OUT_ENABLE 6
#define GP1_OUT_ENABLE 5
#define GP0_OUT_ENABLE 4
#define GP3_DATA 3
#define GP2_DATA 2
#define GP1_DATA 1
#define GP0_DATA 0
#define RDK2_LEDSW 0x14
#define LED3 27
#define LED2 26
#define LED1 25
#define LED0 24
#define PBUTTON 16
#define DIPSW 0
#define RDK2_DIAG 0x18
#define RDK2_FAST_TIMES 2
#define FORCE_PCI_SERR 1
#define FORCE_PCI_INT 0
#define RDK2_FPGAREV 0x1C
/* Dma Control registers */
#define RDK2_DMACTL 0x80
#define ADDR_HOLD 24
#define RETRY_COUNT 16 /* 23:16 */
#define FIFO_THRESHOLD 11 /* 15:11 */
#define MEM_WRITE_INVALIDATE 10
#define READ_MULTIPLE 9
#define READ_LINE 8
#define RDK2_DMA_MODE 6 /* 7:6 */
#define CONTROL_DACK 5
#define EOT_ENABLE 4
#define EOT_POLARITY 3
#define DACK_POLARITY 2
#define DREQ_POLARITY 1
#define DMA_ENABLE 0
#define RDK2_DMASTAT 0x84
#define GATHER_COUNT 12 /* 14:12 */
#define FIFO_COUNT 6 /* 11:6 */
#define FIFO_FLUSH 5
#define FIFO_TRANSFER 4
#define PAUSE_DONE 3
#define ABORT_DONE 2
#define DMA_ABORT 1
#define DMA_START 0
#define RDK2_DMAPCICOUNT 0x88
#define DMA_DIRECTION 31
#define DMA_PCI_BYTE_COUNT 0 /* 0:23 */
#define RDK2_DMALOCCOUNT 0x8C /* 0:23 dma local byte count */
#define RDK2_DMAADDR 0x90 /* 2:31 PCI bus starting address */
/*---------------------------------------------------------------------------*/
#define REG_INDEXED_THRESHOLD (1 << 5)
/* DRIVER DATA STRUCTURES and UTILITIES */
struct net2272_ep {
struct usb_ep ep;
struct net2272 *dev;
unsigned long irqs;
/* analogous to a host-side qh */
struct list_head queue;
const struct usb_endpoint_descriptor *desc;
unsigned num:8,
fifo_size:12,
stopped:1,
wedged:1,
is_in:1,
is_iso:1,
dma:1,
not_empty:1;
};
struct net2272 {
/* each device provides one gadget, several endpoints */
struct usb_gadget gadget;
struct device *dev;
unsigned short dev_id;
spinlock_t lock;
struct net2272_ep ep[4];
struct usb_gadget_driver *driver;
unsigned protocol_stall:1,
softconnect:1,
is_selfpowered:1,
wakeup:1,
dma_eot_polarity:1,
dma_dack_polarity:1,
dma_dreq_polarity:1,
dma_busy:1;
u16 chiprev;
u8 pagesel;
unsigned int irq;
unsigned short fifo_mode;
unsigned int base_shift;
u16 __iomem *base_addr;
union {
#ifdef CONFIG_PCI
struct {
void __iomem *plx9054_base_addr;
void __iomem *epld_base_addr;
} rdk1;
struct {
/* Bar0, Bar1 is base_addr both mem-mapped */
void __iomem *fpga_base_addr;
} rdk2;
#endif
};
};
static void __iomem *
net2272_reg_addr(struct net2272 *dev, unsigned int reg)
{
return dev->base_addr + (reg << dev->base_shift);
}
static void
net2272_write(struct net2272 *dev, unsigned int reg, u8 value)
{
if (reg >= REG_INDEXED_THRESHOLD) {
/*
* Indexed register; use REGADDRPTR/REGDATA
* - Save and restore REGADDRPTR. This prevents REGADDRPTR from
* changes between other code sections, but it is time consuming.
* - Performance tips: either do not save and restore REGADDRPTR (if it
* is safe) or do save/restore operations only in critical sections.
u8 tmp = readb(dev->base_addr + REGADDRPTR);
*/
writeb((u8)reg, net2272_reg_addr(dev, REGADDRPTR));
writeb(value, net2272_reg_addr(dev, REGDATA));
/* writeb(tmp, net2272_reg_addr(dev, REGADDRPTR)); */
} else
writeb(value, net2272_reg_addr(dev, reg));
}
static u8
net2272_read(struct net2272 *dev, unsigned int reg)
{
u8 ret;
if (reg >= REG_INDEXED_THRESHOLD) {
/*
* Indexed register; use REGADDRPTR/REGDATA
* - Save and restore REGADDRPTR. This prevents REGADDRPTR from
* changes between other code sections, but it is time consuming.
* - Performance tips: either do not save and restore REGADDRPTR (if it
* is safe) or do save/restore operations only in critical sections.
u8 tmp = readb(dev->base_addr + REGADDRPTR);
*/
writeb((u8)reg, net2272_reg_addr(dev, REGADDRPTR));
ret = readb(net2272_reg_addr(dev, REGDATA));
/* writeb(tmp, net2272_reg_addr(dev, REGADDRPTR)); */
} else
ret = readb(net2272_reg_addr(dev, reg));
return ret;
}
static void
net2272_ep_write(struct net2272_ep *ep, unsigned int reg, u8 value)
{
struct net2272 *dev = ep->dev;
if (dev->pagesel != ep->num) {
net2272_write(dev, PAGESEL, ep->num);
dev->pagesel = ep->num;
}
net2272_write(dev, reg, value);
}
static u8
net2272_ep_read(struct net2272_ep *ep, unsigned int reg)
{
struct net2272 *dev = ep->dev;
if (dev->pagesel != ep->num) {
net2272_write(dev, PAGESEL, ep->num);
dev->pagesel = ep->num;
}
return net2272_read(dev, reg);
}
static void allow_status(struct net2272_ep *ep)
{
/* ep0 only */
net2272_ep_write(ep, EP_RSPCLR,
(1 << CONTROL_STATUS_PHASE_HANDSHAKE) |
(1 << ALT_NAK_OUT_PACKETS) |
(1 << NAK_OUT_PACKETS_MODE));
ep->stopped = 1;
}
static void set_halt(struct net2272_ep *ep)
{
/* ep0 and bulk/intr endpoints */
net2272_ep_write(ep, EP_RSPCLR, 1 << CONTROL_STATUS_PHASE_HANDSHAKE);
net2272_ep_write(ep, EP_RSPSET, 1 << ENDPOINT_HALT);
}
static void clear_halt(struct net2272_ep *ep)
{
/* ep0 and bulk/intr endpoints */
net2272_ep_write(ep, EP_RSPCLR,
(1 << ENDPOINT_HALT) | (1 << ENDPOINT_TOGGLE));
}
/* count (<= 4) bytes in the next fifo write will be valid */
static void set_fifo_bytecount(struct net2272_ep *ep, unsigned count)
{
/* net2272_ep_write will truncate to u8 for us */
net2272_ep_write(ep, EP_TRANSFER2, count >> 16);
net2272_ep_write(ep, EP_TRANSFER1, count >> 8);
net2272_ep_write(ep, EP_TRANSFER0, count);
}
struct net2272_request {
struct usb_request req;
struct list_head queue;
unsigned mapped:1,
valid:1;
};
#endif

Просмотреть файл

@ -1410,11 +1410,17 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
return 0;
}
static int net2280_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int net2280_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops net2280_ops = {
.get_frame = net2280_get_frame,
.wakeup = net2280_wakeup,
.set_selfpowered = net2280_set_selfpowered,
.pullup = net2280_pullup,
.start = net2280_start,
.stop = net2280_stop,
};
/*-------------------------------------------------------------------------*/
@ -1738,62 +1744,6 @@ static void set_fifo_mode (struct net2280 *dev, int mode)
list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list);
}
/* just declare this in any driver that really need it */
extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
/**
* net2280_set_fifo_mode - change allocation of fifo buffers
* @gadget: access to the net2280 device that will be updated
* @mode: 0 for default, four 1kB buffers (ep-a through ep-d);
* 1 for two 2kB buffers (ep-a and ep-b only);
* 2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
*
* returns zero on success, else negative errno. when this succeeds,
* the contents of gadget->ep_list may have changed.
*
* you may only call this function when endpoints a-d are all disabled.
* use it whenever extra hardware buffering can help performance, such
* as before enabling "high bandwidth" interrupt endpoints that use
* maxpacket bigger than 512 (when double buffering would otherwise
* be unavailable).
*/
int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode)
{
int i;
struct net2280 *dev;
int status = 0;
unsigned long flags;
if (!gadget)
return -ENODEV;
dev = container_of (gadget, struct net2280, gadget);
spin_lock_irqsave (&dev->lock, flags);
for (i = 1; i <= 4; i++)
if (dev->ep [i].desc) {
status = -EINVAL;
break;
}
if (mode < 0 || mode > 2)
status = -EINVAL;
if (status == 0)
set_fifo_mode (dev, mode);
spin_unlock_irqrestore (&dev->lock, flags);
if (status == 0) {
if (mode == 1)
DEBUG (dev, "fifo: ep-a 2K, ep-b 2K\n");
else if (mode == 2)
DEBUG (dev, "fifo: ep-a 2K, ep-b 1K, ep-c 1K\n");
/* else all are 1K */
}
return status;
}
EXPORT_SYMBOL (net2280_set_fifo_mode);
/*-------------------------------------------------------------------------*/
/* keeping it simple:
* - one bus driver, initted first;
* - one function driver, initted second
@ -1930,7 +1880,7 @@ static void ep0_start (struct net2280 *dev)
* disconnect is reported. then a host may connect again, or
* the driver might get unbound.
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int net2280_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct net2280 *dev = the_controller;
@ -1994,7 +1944,6 @@ err_unbind:
dev->driver = NULL;
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
static void
stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
@ -2022,7 +1971,7 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
usb_reinit (dev);
}
int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
static int net2280_stop(struct usb_gadget_driver *driver)
{
struct net2280 *dev = the_controller;
unsigned long flags;
@ -2049,8 +1998,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name);
return 0;
}
EXPORT_SYMBOL (usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------*/
@ -2732,6 +2679,8 @@ static void net2280_remove (struct pci_dev *pdev)
{
struct net2280 *dev = pci_get_drvdata (pdev);
usb_del_gadget_udc(&dev->gadget);
BUG_ON(dev->driver);
/* then clean up the resources we allocated during probe() */
@ -2916,6 +2865,9 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
retval = device_create_file (&pdev->dev, &dev_attr_registers);
if (retval) goto done;
retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
if (retval)
goto done;
return 0;
done:

Просмотреть файл

@ -241,6 +241,7 @@ static struct usb_composite_driver nokia_driver = {
.name = "g_nokia",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = __exit_p(nokia_unbind),
};

Просмотреть файл

@ -1375,6 +1375,10 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
static int omap_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int omap_udc_stop(struct usb_gadget_driver *driver);
static struct usb_gadget_ops omap_gadget_ops = {
.get_frame = omap_get_frame,
.wakeup = omap_wakeup,
@ -1382,6 +1386,8 @@ static struct usb_gadget_ops omap_gadget_ops = {
.vbus_session = omap_vbus_session,
.vbus_draw = omap_vbus_draw,
.pullup = omap_pullup,
.start = omap_udc_start,
.stop = omap_udc_stop,
};
/*-------------------------------------------------------------------------*/
@ -2102,7 +2108,7 @@ static inline int machine_without_vbus_sense(void)
);
}
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int omap_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
int status = -ENODEV;
@ -2186,9 +2192,8 @@ done:
omap_udc_enable_clock(0);
return status;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
static int omap_udc_stop(struct usb_gadget_driver *driver)
{
unsigned long flags;
int status = -ENODEV;
@ -2222,8 +2227,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
DBG("unregistered driver '%s'\n", driver->driver.name);
return status;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------*/
@ -2991,9 +2994,16 @@ known:
create_proc_file();
status = device_add(&udc->gadget.dev);
if (status)
goto cleanup4;
status = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (!status)
return status;
/* If fail, fall through */
cleanup4:
remove_proc_file();
#ifdef USE_ISO
cleanup3:
free_irq(pdev->resource[2].start, udc);
@ -3029,6 +3039,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
if (!udc)
return -ENODEV;
usb_del_gadget_udc(&udc->gadget);
if (udc->driver)
return -EBUSY;

Просмотреть файл

@ -1176,6 +1176,9 @@ static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
return -EOPNOTSUPP;
}
static int pch_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int pch_udc_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops pch_udc_ops = {
.get_frame = pch_udc_pcd_get_frame,
.wakeup = pch_udc_pcd_wakeup,
@ -1183,6 +1186,8 @@ static const struct usb_gadget_ops pch_udc_ops = {
.pullup = pch_udc_pcd_pullup,
.vbus_session = pch_udc_pcd_vbus_session,
.vbus_draw = pch_udc_pcd_vbus_draw,
.start = pch_udc_start,
.stop = pch_udc_stop,
};
/**
@ -2690,7 +2695,7 @@ static int init_dma_pools(struct pch_udc_dev *dev)
return 0;
}
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int pch_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct pch_udc_dev *dev = pch_udc;
@ -2733,9 +2738,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
dev->connected = 1;
return 0;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int pch_udc_stop(struct usb_gadget_driver *driver)
{
struct pch_udc_dev *dev = pch_udc;
@ -2761,7 +2765,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
pch_udc_set_disconnect(dev);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
static void pch_udc_shutdown(struct pci_dev *pdev)
{
@ -2778,6 +2781,8 @@ static void pch_udc_remove(struct pci_dev *pdev)
{
struct pch_udc_dev *dev = pci_get_drvdata(pdev);
usb_del_gadget_udc(&dev->gadget);
/* gadget driver must not be registered */
if (dev->driver)
dev_err(&pdev->dev,
@ -2953,6 +2958,9 @@ static int pch_udc_probe(struct pci_dev *pdev,
/* Put the device in disconnected state till a driver is bound */
pch_udc_set_disconnect(dev);
retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
if (retval)
goto finished;
return 0;
finished:

Просмотреть файл

@ -89,8 +89,7 @@ struct printer_dev {
u8 config;
s8 interface;
struct usb_ep *in_ep, *out_ep;
const struct usb_endpoint_descriptor
*in, *out;
struct list_head rx_reqs; /* List of free RX structs */
struct list_head rx_reqs_active; /* List of Active RX xfers */
struct list_head rx_buffers; /* List of completed xfers */
@ -898,19 +897,20 @@ set_printer_interface(struct printer_dev *dev)
{
int result = 0;
dev->in = ep_desc(dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc);
dev->in_ep->desc = ep_desc(dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc);
dev->in_ep->driver_data = dev;
dev->out = ep_desc(dev->gadget, &hs_ep_out_desc, &fs_ep_out_desc);
dev->out_ep->desc = ep_desc(dev->gadget, &hs_ep_out_desc,
&fs_ep_out_desc);
dev->out_ep->driver_data = dev;
result = usb_ep_enable(dev->in_ep, dev->in);
result = usb_ep_enable(dev->in_ep);
if (result != 0) {
DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
goto done;
}
result = usb_ep_enable(dev->out_ep, dev->out);
result = usb_ep_enable(dev->out_ep);
if (result != 0) {
DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
goto done;
@ -921,8 +921,8 @@ done:
if (result != 0) {
(void) usb_ep_disable(dev->in_ep);
(void) usb_ep_disable(dev->out_ep);
dev->in = NULL;
dev->out = NULL;
dev->in_ep->desc = NULL;
dev->out_ep->desc = NULL;
}
/* caller is responsible for cleanup on error */
@ -936,12 +936,14 @@ static void printer_reset_interface(struct printer_dev *dev)
DBG(dev, "%s\n", __func__);
if (dev->in)
if (dev->in_ep->desc)
usb_ep_disable(dev->in_ep);
if (dev->out)
if (dev->out_ep->desc)
usb_ep_disable(dev->out_ep);
dev->in_ep->desc = NULL;
dev->out_ep->desc = NULL;
dev->interface = -1;
}
@ -1107,9 +1109,9 @@ static void printer_soft_reset(struct printer_dev *dev)
list_add(&req->list, &dev->tx_reqs);
}
if (usb_ep_enable(dev->in_ep, dev->in))
if (usb_ep_enable(dev->in_ep))
DBG(dev, "Failed to enable USB in_ep\n");
if (usb_ep_enable(dev->out_ep, dev->out))
if (usb_ep_enable(dev->out_ep))
DBG(dev, "Failed to enable USB out_ep\n");
wake_up_interruptible(&dev->rx_wait);
@ -1149,6 +1151,8 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
switch (wValue >> 8) {
case USB_DT_DEVICE:
device_desc.bMaxPacketSize0 =
gadget->ep0->maxpacket;
value = min(wLength, (u16) sizeof device_desc);
memcpy(req->buf, &device_desc, value);
break;
@ -1156,6 +1160,12 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_DT_DEVICE_QUALIFIER:
if (!gadget->is_dualspeed)
break;
/*
* assumes ep0 uses the same value for both
* speeds
*/
dev_qualifier.bMaxPacketSize0 =
gadget->ep0->maxpacket;
value = min(wLength,
(u16) sizeof dev_qualifier);
memcpy(req->buf, &dev_qualifier, value);
@ -1451,15 +1461,11 @@ autoconf_fail:
out_ep->driver_data = out_ep; /* claim */
#ifdef CONFIG_USB_GADGET_DUALSPEED
/* assumes ep0 uses the same value for both speeds ... */
dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
/* and that all endpoints are dual-speed */
/* assumes that all endpoints are dual-speed */
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
#endif /* DUALSPEED */
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
usb_gadget_set_selfpowered(gadget);
if (gadget->is_otg) {

Просмотреть файл

@ -1011,12 +1011,18 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
return -EOPNOTSUPP;
}
static int pxa25x_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int pxa25x_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops pxa25x_udc_ops = {
.get_frame = pxa25x_udc_get_frame,
.wakeup = pxa25x_udc_wakeup,
.vbus_session = pxa25x_udc_vbus_session,
.pullup = pxa25x_udc_pullup,
.vbus_draw = pxa25x_udc_vbus_draw,
.start = pxa25x_start,
.stop = pxa25x_stop,
};
/*-------------------------------------------------------------------------*/
@ -1263,7 +1269,7 @@ static void udc_enable (struct pxa25x_udc *dev)
* disconnect is reported. then a host may connect again, or
* the driver might get unbound.
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int pxa25x_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct pxa25x_udc *dev = the_controller;
@ -1322,7 +1328,6 @@ fail:
bind_fail:
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
static void
stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
@ -1351,7 +1356,7 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
udc_reinit(dev);
}
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int pxa25x_stop(struct usb_gadget_driver *driver)
{
struct pxa25x_udc *dev = the_controller;
@ -1379,8 +1384,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
dump_state(dev);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------*/
@ -2231,8 +2234,11 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
#endif
create_debug_files(dev);
return 0;
retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
if (!retval)
return retval;
remove_debug_files(dev);
#ifdef CONFIG_ARCH_LUBBOCK
lubbock_fail0:
free_irq(LUBBOCK_USB_DISC_IRQ, dev);
@ -2261,6 +2267,7 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
{
struct pxa25x_udc *dev = platform_get_drvdata(pdev);
usb_del_gadget_udc(&dev->gadget);
if (dev->driver)
return -EBUSY;

Просмотреть файл

@ -1680,12 +1680,18 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
return -EOPNOTSUPP;
}
static int pxa27x_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int pxa27x_udc_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops pxa_udc_ops = {
.get_frame = pxa_udc_get_frame,
.wakeup = pxa_udc_wakeup,
.pullup = pxa_udc_pullup,
.vbus_session = pxa_udc_vbus_session,
.vbus_draw = pxa_udc_vbus_draw,
.start = pxa27x_udc_start,
.stop = pxa27x_udc_stop,
};
/**
@ -1791,7 +1797,7 @@ static void udc_enable(struct pxa_udc *udc)
}
/**
* usb_gadget_probe_driver - Register gadget driver
* pxa27x_start - Register gadget driver
* @driver: gadget driver
* @bind: bind function
*
@ -1805,7 +1811,7 @@ static void udc_enable(struct pxa_udc *udc)
*
* Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int pxa27x_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct pxa_udc *udc = the_controller;
@ -1860,8 +1866,6 @@ add_fail:
udc->gadget.dev.driver = NULL;
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
/**
* stop_activity - Stops udc endpoints
@ -1888,12 +1892,12 @@ static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver)
}
/**
* usb_gadget_unregister_driver - Unregister the gadget driver
* pxa27x_udc_stop - Unregister the gadget driver
* @driver: gadget driver
*
* Returns 0 if no error, -ENODEV, -EINVAL otherwise
*/
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int pxa27x_udc_stop(struct usb_gadget_driver *driver)
{
struct pxa_udc *udc = the_controller;
@ -1917,7 +1921,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return otg_set_peripheral(udc->transceiver, NULL);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/**
* handle_ep0_ctrl_req - handle control endpoint control request
@ -2516,9 +2519,14 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
driver_name, IRQ_USB, retval);
goto err_irq;
}
retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (retval)
goto err_add_udc;
pxa_init_debugfs(udc);
return 0;
err_add_udc:
free_irq(udc->irq, udc);
err_irq:
iounmap(udc->regs);
err_map:
@ -2537,6 +2545,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
struct pxa_udc *udc = platform_get_drvdata(_dev);
int gpio = udc->mach->gpio_pullup;
usb_del_gadget_udc(&udc->gadget);
usb_gadget_unregister_driver(udc->driver);
free_irq(udc->irq, udc);
pxa_cleanup_debugfs(udc);

Просмотреть файл

@ -3,7 +3,7 @@
*
* Copyright (C) 2006-2009 Renesas Solutions Corp.
*
* Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
* Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -576,7 +576,11 @@ static void init_controller(struct r8a66597 *r8a66597)
u16 endian = r8a66597->pdata->endian ? BIGEND : 0;
if (r8a66597->pdata->on_chip) {
r8a66597_bset(r8a66597, 0x04, SYSCFG1);
if (r8a66597->pdata->buswait)
r8a66597_write(r8a66597, r8a66597->pdata->buswait,
SYSCFG1);
else
r8a66597_write(r8a66597, 0x0f, SYSCFG1);
r8a66597_bset(r8a66597, HSE, SYSCFG0);
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
@ -618,6 +622,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
{
if (r8a66597->pdata->on_chip) {
r8a66597_bset(r8a66597, SCKE, SYSCFG0);
r8a66597_bclr(r8a66597, UTST, TESTMODE);
/* disable interrupts */
r8a66597_write(r8a66597, 0, INTENB0);
@ -635,6 +640,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
} else {
r8a66597_bclr(r8a66597, UTST, TESTMODE);
r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
udelay(1);
r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
@ -999,10 +1005,29 @@ static void clear_feature(struct r8a66597 *r8a66597,
static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
{
u16 tmp;
int timeout = 3000;
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
control_end(r8a66597, 1);
switch (le16_to_cpu(ctrl->wValue)) {
case USB_DEVICE_TEST_MODE:
control_end(r8a66597, 1);
/* Wait for the completion of status stage */
do {
tmp = r8a66597_read(r8a66597, INTSTS0) & CTSQ;
udelay(1);
} while (tmp != CS_IDST || timeout-- > 0);
if (tmp == CS_IDST)
r8a66597_bset(r8a66597,
le16_to_cpu(ctrl->wIndex >> 8),
TESTMODE);
break;
default:
pipe_stall(r8a66597, 0);
break;
}
break;
case USB_RECIP_INTERFACE:
control_end(r8a66597, 1);
@ -1410,7 +1435,7 @@ static struct usb_ep_ops r8a66597_ep_ops = {
/*-------------------------------------------------------------------------*/
static struct r8a66597 *the_controller;
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int r8a66597_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct r8a66597 *r8a66597 = the_controller;
@ -1444,6 +1469,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
goto error;
}
init_controller(r8a66597);
r8a66597_bset(r8a66597, VBSE, INTENB0);
if (r8a66597_read(r8a66597, INTSTS0) & VBSTS) {
r8a66597_start_xclock(r8a66597);
@ -1462,9 +1488,8 @@ error:
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int r8a66597_stop(struct usb_gadget_driver *driver)
{
struct r8a66597 *r8a66597 = the_controller;
unsigned long flags;
@ -1475,20 +1500,16 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
spin_lock_irqsave(&r8a66597->lock, flags);
if (r8a66597->gadget.speed != USB_SPEED_UNKNOWN)
r8a66597_usb_disconnect(r8a66597);
r8a66597_bclr(r8a66597, VBSE, INTENB0);
disable_controller(r8a66597);
spin_unlock_irqrestore(&r8a66597->lock, flags);
r8a66597_bclr(r8a66597, VBSE, INTENB0);
driver->unbind(&r8a66597->gadget);
init_controller(r8a66597);
disable_controller(r8a66597);
device_del(&r8a66597->gadget.dev);
r8a66597->driver = NULL;
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
/*-------------------------------------------------------------------------*/
static int r8a66597_get_frame(struct usb_gadget *_gadget)
@ -1497,14 +1518,33 @@ static int r8a66597_get_frame(struct usb_gadget *_gadget)
return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
}
static int r8a66597_pullup(struct usb_gadget *gadget, int is_on)
{
struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
unsigned long flags;
spin_lock_irqsave(&r8a66597->lock, flags);
if (is_on)
r8a66597_bset(r8a66597, DPRPU, SYSCFG0);
else
r8a66597_bclr(r8a66597, DPRPU, SYSCFG0);
spin_unlock_irqrestore(&r8a66597->lock, flags);
return 0;
}
static struct usb_gadget_ops r8a66597_gadget_ops = {
.get_frame = r8a66597_get_frame,
.start = r8a66597_start,
.stop = r8a66597_stop,
.pullup = r8a66597_pullup,
};
static int __exit r8a66597_remove(struct platform_device *pdev)
{
struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
usb_del_gadget_udc(&r8a66597->gadget);
del_timer_sync(&r8a66597->timer);
iounmap(r8a66597->reg);
free_irq(platform_get_irq(pdev, 0), r8a66597);
@ -1645,11 +1685,15 @@ static int __init r8a66597_probe(struct platform_device *pdev)
goto clean_up3;
r8a66597->ep0_req->complete = nop_completion;
init_controller(r8a66597);
ret = usb_add_gadget_udc(&pdev->dev, &r8a66597->gadget);
if (ret)
goto err_add_udc;
dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
return 0;
err_add_udc:
r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);
clean_up3:
free_irq(irq, r8a66597);
clean_up2:
@ -1679,6 +1723,7 @@ static struct platform_driver r8a66597_driver = {
.name = (char *) udc_name,
},
};
MODULE_ALIAS("platform:r8a66597_udc");
static int __init r8a66597_udc_init(void)
{

Просмотреть файл

@ -3,7 +3,7 @@
*
* Copyright (C) 2007-2009 Renesas Solutions Corp.
*
* Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
* Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

Просмотреть файл

@ -2574,7 +2574,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
return 0;
}
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int s3c_hsotg_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct s3c_hsotg *hsotg = our_hsotg;
@ -2745,9 +2745,8 @@ err:
hsotg->gadget.dev.driver = NULL;
return ret;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int s3c_hsotg_stop(struct usb_gadget_driver *driver)
{
struct s3c_hsotg *hsotg = our_hsotg;
int ep;
@ -2775,7 +2774,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
{
@ -2784,6 +2782,8 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
.get_frame = s3c_hsotg_gadget_getframe,
.start = s3c_hsotg_start,
.stop = s3c_hsotg_stop,
};
/**
@ -3403,6 +3403,10 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++)
s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
if (ret)
goto err_add_udc;
s3c_hsotg_create_debug(hsotg);
s3c_hsotg_dump(hsotg);
@ -3410,6 +3414,11 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
our_hsotg = hsotg;
return 0;
err_add_udc:
s3c_hsotg_gate(pdev, false);
clk_disable(hsotg->clk);
clk_put(hsotg->clk);
err_regs:
iounmap(hsotg->regs);
@ -3427,6 +3436,8 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
{
struct s3c_hsotg *hsotg = platform_get_drvdata(pdev);
usb_del_gadget_udc(&hsotg->gadget);
s3c_hsotg_delete_debug(hsotg);
usb_gadget_unregister_driver(hsotg->driver);

Просмотреть файл

@ -1133,7 +1133,7 @@ static irqreturn_t s3c_hsudc_irq(int irq, void *_dev)
return IRQ_HANDLED;
}
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int s3c_hsudc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct s3c_hsudc *hsudc = the_controller;
@ -1181,9 +1181,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
return 0;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int s3c_hsudc_stop(struct usb_gadget_driver *driver)
{
struct s3c_hsudc *hsudc = the_controller;
unsigned long flags;
@ -1210,7 +1209,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
static inline u32 s3c_hsudc_read_frameno(struct s3c_hsudc *hsudc)
{
@ -1224,6 +1222,8 @@ static int s3c_hsudc_gadget_getframe(struct usb_gadget *gadget)
static struct usb_gadget_ops s3c_hsudc_gadget_ops = {
.get_frame = s3c_hsudc_gadget_getframe,
.start = s3c_hsudc_start,
.stop = s3c_hsudc_stop,
};
static int s3c_hsudc_probe(struct platform_device *pdev)
@ -1311,7 +1311,15 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
disable_irq(hsudc->irq);
local_irq_enable();
ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
if (ret)
goto err_add_udc;
return 0;
err_add_udc:
clk_disable(hsudc->uclk);
clk_put(hsudc->uclk);
err_clk:
free_irq(hsudc->irq, hsudc);
err_irq:
@ -1333,6 +1341,7 @@ static struct platform_driver s3c_hsudc_driver = {
},
.probe = s3c_hsudc_probe,
};
MODULE_ALIAS("platform:s3c-hsudc");
static int __init s3c_hsudc_modinit(void)
{

Просмотреть файл

@ -1552,6 +1552,10 @@ static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
return -ENOTSUPP;
}
static int s3c2410_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *));
static int s3c2410_udc_stop(struct usb_gadget_driver *driver);
static const struct usb_gadget_ops s3c2410_ops = {
.get_frame = s3c2410_udc_get_frame,
.wakeup = s3c2410_udc_wakeup,
@ -1559,6 +1563,8 @@ static const struct usb_gadget_ops s3c2410_ops = {
.pullup = s3c2410_udc_pullup,
.vbus_session = s3c2410_udc_vbus_session,
.vbus_draw = s3c2410_vbus_draw,
.start = s3c2410_udc_start,
.stop = s3c2410_udc_stop,
};
static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
@ -1567,7 +1573,7 @@ static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
return;
if (udc_info->udc_command) {
udc_info->udc_command(S3C2410_UDC_P_DISABLE);
udc_info->udc_command(cmd);
} else if (gpio_is_valid(udc_info->pullup_pin)) {
int value;
@ -1672,10 +1678,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
}
/*
* usb_gadget_probe_driver
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
static int s3c2410_udc_start(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct s3c2410_udc *udc = the_controller;
@ -1730,12 +1733,8 @@ register_error:
udc->gadget.dev.driver = NULL;
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
/*
* usb_gadget_unregister_driver
*/
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
static int s3c2410_udc_stop(struct usb_gadget_driver *driver)
{
struct s3c2410_udc *udc = the_controller;
@ -1955,6 +1954,10 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
goto err_vbus_irq;
}
retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (retval)
goto err_add_udc;
if (s3c2410_udc_debugfs_root) {
udc->regs_info = debugfs_create_file("registers", S_IRUGO,
s3c2410_udc_debugfs_root,
@ -1967,6 +1970,10 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
return 0;
err_add_udc:
if (udc_info && !udc_info->udc_command &&
gpio_is_valid(udc_info->pullup_pin))
gpio_free(udc_info->pullup_pin);
err_vbus_irq:
if (udc_info && udc_info->vbus_pin > 0)
free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
@ -1992,6 +1999,8 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
unsigned int irq;
dev_dbg(&pdev->dev, "%s()\n", __func__);
usb_del_gadget_udc(&udc->gadget);
if (udc->driver)
return -EBUSY;
@ -2048,26 +2057,22 @@ static int s3c2410_udc_resume(struct platform_device *pdev)
#define s3c2410_udc_resume NULL
#endif
static struct platform_driver udc_driver_2410 = {
.driver = {
.name = "s3c2410-usbgadget",
.owner = THIS_MODULE,
},
.probe = s3c2410_udc_probe,
.remove = s3c2410_udc_remove,
.suspend = s3c2410_udc_suspend,
.resume = s3c2410_udc_resume,
static const struct platform_device_id s3c_udc_ids[] = {
{ "s3c2410-usbgadget", },
{ "s3c2440-usbgadget", },
};
MODULE_DEVICE_TABLE(platform, s3c_udc_ids);
static struct platform_driver udc_driver_2440 = {
static struct platform_driver udc_driver_24x0 = {
.driver = {
.name = "s3c2440-usbgadget",
.name = "s3c24x0-usbgadget",
.owner = THIS_MODULE,
},
.probe = s3c2410_udc_probe,
.remove = s3c2410_udc_remove,
.suspend = s3c2410_udc_suspend,
.resume = s3c2410_udc_resume,
.id_table = s3c_udc_ids,
};
static int __init udc_init(void)
@ -2083,11 +2088,7 @@ static int __init udc_init(void)
s3c2410_udc_debugfs_root = NULL;
}
retval = platform_driver_register(&udc_driver_2410);
if (retval)
goto err;
retval = platform_driver_register(&udc_driver_2440);
retval = platform_driver_register(&udc_driver_24x0);
if (retval)
goto err;
@ -2100,13 +2101,10 @@ err:
static void __exit udc_exit(void)
{
platform_driver_unregister(&udc_driver_2410);
platform_driver_unregister(&udc_driver_2440);
platform_driver_unregister(&udc_driver_24x0);
debugfs_remove(s3c2410_udc_debugfs_root);
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
module_init(udc_init);
module_exit(udc_exit);
@ -2114,5 +2112,3 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:s3c2410-usbgadget");
MODULE_ALIAS("platform:s3c2440-usbgadget");

Просмотреть файл

@ -242,6 +242,7 @@ static struct usb_composite_driver gserial_driver = {
.name = "g_serial",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
};
static int __init init(void)

Просмотреть файл

@ -494,7 +494,7 @@ static struct usb_descriptor_header *fsg_hs_function[] = {
};
/* Maxpacket and other transfer characteristics vary by speed. */
static struct usb_endpoint_descriptor *
static __maybe_unused struct usb_endpoint_descriptor *
fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
struct usb_endpoint_descriptor *hs)
{

Просмотреть файл

@ -97,16 +97,17 @@ struct eth_dev {
static unsigned qmult = 5;
module_param(qmult, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(qmult, "queue length multiplier at high speed");
MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed");
#else /* full speed (low speed doesn't do bulk) */
#define qmult 1
#endif
/* for dual-speed hardware, use deeper queues at highspeed */
/* for dual-speed hardware, use deeper queues at high/super speed */
static inline int qlen(struct usb_gadget *gadget)
{
if (gadget_is_dualspeed(gadget) && gadget->speed == USB_SPEED_HIGH)
if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH ||
gadget->speed == USB_SPEED_SUPER))
return qmult * DEFAULT_QLEN;
else
return DEFAULT_QLEN;
@ -598,9 +599,10 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
req->length = length;
/* throttle highspeed IRQ rate back slightly */
/* throttle high/super speed IRQ rate back slightly */
if (gadget_is_dualspeed(dev->gadget))
req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH ||
dev->gadget->speed == USB_SPEED_SUPER)
? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
: 0;
@ -693,8 +695,8 @@ static int eth_stop(struct net_device *net)
usb_ep_disable(link->out_ep);
if (netif_carrier_ok(net)) {
DBG(dev, "host still using in/out endpoints\n");
usb_ep_enable(link->in_ep, link->in);
usb_ep_enable(link->out_ep, link->out);
usb_ep_enable(link->in_ep);
usb_ep_enable(link->out_ep);
}
}
spin_unlock_irqrestore(&dev->lock, flags);
@ -871,7 +873,7 @@ struct net_device *gether_connect(struct gether *link)
return ERR_PTR(-EINVAL);
link->in_ep->driver_data = dev;
result = usb_ep_enable(link->in_ep, link->in);
result = usb_ep_enable(link->in_ep);
if (result != 0) {
DBG(dev, "enable %s --> %d\n",
link->in_ep->name, result);
@ -879,7 +881,7 @@ struct net_device *gether_connect(struct gether *link)
}
link->out_ep->driver_data = dev;
result = usb_ep_enable(link->out_ep, link->out);
result = usb_ep_enable(link->out_ep);
if (result != 0) {
DBG(dev, "enable %s --> %d\n",
link->out_ep->name, result);
@ -969,7 +971,7 @@ void gether_disconnect(struct gether *link)
}
spin_unlock(&dev->req_lock);
link->in_ep->driver_data = NULL;
link->in = NULL;
link->in_ep->desc = NULL;
usb_ep_disable(link->out_ep);
spin_lock(&dev->req_lock);
@ -984,7 +986,7 @@ void gether_disconnect(struct gether *link)
}
spin_unlock(&dev->req_lock);
link->out_ep->driver_data = NULL;
link->out = NULL;
link->out_ep->desc = NULL;
/* finish forgetting about this USB link episode */
dev->header_len = 0;

Просмотреть файл

@ -52,10 +52,6 @@ struct gether {
struct usb_ep *in_ep;
struct usb_ep *out_ep;
/* descriptors match device speed at gether_connect() time */
struct usb_endpoint_descriptor *in;
struct usb_endpoint_descriptor *out;
bool is_zlp_ok;
u16 cdc_filter;

Просмотреть файл

@ -1247,12 +1247,12 @@ int gserial_connect(struct gserial *gser, u8 port_num)
port = ports[port_num].port;
/* activate the endpoints */
status = usb_ep_enable(gser->in, gser->in_desc);
status = usb_ep_enable(gser->in);
if (status < 0)
return status;
gser->in->driver_data = port;
status = usb_ep_enable(gser->out, gser->out_desc);
status = usb_ep_enable(gser->out);
if (status < 0)
goto fail_out;
gser->out->driver_data = port;

Просмотреть файл

@ -35,8 +35,6 @@ struct gserial {
struct usb_ep *in;
struct usb_ep *out;
struct usb_endpoint_descriptor *in_desc;
struct usb_endpoint_descriptor *out_desc;
/* REVISIT avoid this CDC-ACM support harder ... */
struct usb_cdc_line_coding port_line_coding; /* 9600-8-N-1 etc */

Просмотреть файл

@ -0,0 +1,484 @@
/**
* udc.c - Core UDC Framework
*
* Copyright (C) 2010 Texas Instruments
* Author: Felipe Balbi <balbi@ti.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 of
* the License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/err.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
/**
* struct usb_udc - describes one usb device controller
* @driver - the gadget driver pointer. For use by the class code
* @dev - the child device to the actual controller
* @gadget - the gadget. For use by the class code
* @list - for use by the udc class driver
*
* This represents the internal data structure which is used by the UDC-class
* to hold information about udc driver and gadget together.
*/
struct usb_udc {
struct usb_gadget_driver *driver;
struct usb_gadget *gadget;
struct device dev;
struct list_head list;
};
static struct class *udc_class;
static LIST_HEAD(udc_list);
static DEFINE_MUTEX(udc_lock);
/* ------------------------------------------------------------------------- */
/**
* usb_gadget_start - tells usb device controller to start up
* @gadget: The gadget we want to get started
* @driver: The driver we want to bind to @gadget
* @bind: The bind function for @driver
*
* This call is issued by the UDC Class driver when it's about
* to register a gadget driver to the device controller, before
* calling gadget driver's bind() method.
*
* It allows the controller to be powered off until strictly
* necessary to have it powered on.
*
* Returns zero on success, else negative errno.
*/
static inline int usb_gadget_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
return gadget->ops->start(driver, bind);
}
/**
* usb_gadget_udc_start - tells usb device controller to start up
* @gadget: The gadget we want to get started
* @driver: The driver we want to bind to @gadget
*
* This call is issued by the UDC Class driver when it's about
* to register a gadget driver to the device controller, before
* calling gadget driver's bind() method.
*
* It allows the controller to be powered off until strictly
* necessary to have it powered on.
*
* Returns zero on success, else negative errno.
*/
static inline int usb_gadget_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
return gadget->ops->udc_start(gadget, driver);
}
/**
* usb_gadget_stop - tells usb device controller we don't need it anymore
* @gadget: The device we want to stop activity
* @driver: The driver to unbind from @gadget
*
* This call is issued by the UDC Class driver after calling
* gadget driver's unbind() method.
*
* The details are implementation specific, but it can go as
* far as powering off UDC completely and disable its data
* line pullups.
*/
static inline void usb_gadget_stop(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
gadget->ops->stop(driver);
}
/**
* usb_gadget_udc_stop - tells usb device controller we don't need it anymore
* @gadget: The device we want to stop activity
* @driver: The driver to unbind from @gadget
*
* This call is issued by the UDC Class driver after calling
* gadget driver's unbind() method.
*
* The details are implementation specific, but it can go as
* far as powering off UDC completely and disable its data
* line pullups.
*/
static inline void usb_gadget_udc_stop(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
gadget->ops->udc_stop(gadget, driver);
}
/**
* usb_udc_release - release the usb_udc struct
* @dev: the dev member within usb_udc
*
* This is called by driver's core in order to free memory once the last
* reference is released.
*/
static void usb_udc_release(struct device *dev)
{
struct usb_udc *udc;
udc = container_of(dev, struct usb_udc, dev);
dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
kfree(udc);
}
static const struct attribute_group *usb_udc_attr_groups[];
/**
* usb_add_gadget_udc - adds a new gadget to the udc class driver list
* @parent: the parent device to this udc. Usually the controller
* driver's device.
* @gadget: the gadget to be added to the list
*
* Returns zero on success, negative errno otherwise.
*/
int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
{
struct usb_udc *udc;
int ret = -ENOMEM;
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
if (!udc)
goto err1;
device_initialize(&udc->dev);
udc->dev.release = usb_udc_release;
udc->dev.class = udc_class;
udc->dev.groups = usb_udc_attr_groups;
udc->dev.parent = parent;
ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
if (ret)
goto err2;
udc->gadget = gadget;
mutex_lock(&udc_lock);
list_add_tail(&udc->list, &udc_list);
ret = device_add(&udc->dev);
if (ret)
goto err3;
mutex_unlock(&udc_lock);
return 0;
err3:
list_del(&udc->list);
mutex_unlock(&udc_lock);
err2:
put_device(&udc->dev);
err1:
return ret;
}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
static int udc_is_newstyle(struct usb_udc *udc)
{
if (udc->gadget->ops->udc_start && udc->gadget->ops->udc_stop)
return 1;
return 0;
}
static void usb_gadget_remove_driver(struct usb_udc *udc)
{
dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
udc->gadget->name);
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
if (udc_is_newstyle(udc)) {
usb_gadget_disconnect(udc->gadget);
udc->driver->unbind(udc->gadget);
usb_gadget_udc_stop(udc->gadget, udc->driver);
} else {
usb_gadget_stop(udc->gadget, udc->driver);
}
udc->driver = NULL;
udc->dev.driver = NULL;
}
/**
* usb_del_gadget_udc - deletes @udc from udc_list
* @gadget: the gadget to be removed.
*
* This, will call usb_gadget_unregister_driver() if
* the @udc is still busy.
*/
void usb_del_gadget_udc(struct usb_gadget *gadget)
{
struct usb_udc *udc = NULL;
mutex_lock(&udc_lock);
list_for_each_entry(udc, &udc_list, list)
if (udc->gadget == gadget)
goto found;
dev_err(gadget->dev.parent, "gadget not registered.\n");
mutex_unlock(&udc_lock);
return;
found:
dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
list_del(&udc->list);
mutex_unlock(&udc_lock);
if (udc->driver)
usb_gadget_remove_driver(udc);
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
device_unregister(&udc->dev);
}
EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
/* ------------------------------------------------------------------------- */
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct usb_udc *udc = NULL;
int ret;
if (!driver || !bind || !driver->setup)
return -EINVAL;
mutex_lock(&udc_lock);
list_for_each_entry(udc, &udc_list, list) {
/* For now we take the first one */
if (!udc->driver)
goto found;
}
pr_debug("couldn't find an available UDC\n");
mutex_unlock(&udc_lock);
return -ENODEV;
found:
dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
driver->function);
udc->driver = driver;
udc->dev.driver = &driver->driver;
if (udc_is_newstyle(udc)) {
ret = bind(udc->gadget);
if (ret)
goto err1;
ret = usb_gadget_udc_start(udc->gadget, driver);
if (ret) {
driver->unbind(udc->gadget);
goto err1;
}
usb_gadget_connect(udc->gadget);
} else {
ret = usb_gadget_start(udc->gadget, driver, bind);
if (ret)
goto err1;
}
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
mutex_unlock(&udc_lock);
return 0;
err1:
dev_err(&udc->dev, "failed to start %s: %d\n",
udc->driver->function, ret);
udc->driver = NULL;
udc->dev.driver = NULL;
mutex_unlock(&udc_lock);
return ret;
}
EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{
struct usb_udc *udc = NULL;
int ret = -ENODEV;
if (!driver || !driver->unbind)
return -EINVAL;
mutex_lock(&udc_lock);
list_for_each_entry(udc, &udc_list, list)
if (udc->driver == driver) {
usb_gadget_remove_driver(udc);
ret = 0;
break;
}
mutex_unlock(&udc_lock);
return ret;
}
EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
/* ------------------------------------------------------------------------- */
static ssize_t usb_udc_srp_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t n)
{
struct usb_udc *udc = dev_get_drvdata(dev);
if (sysfs_streq(buf, "1"))
usb_gadget_wakeup(udc->gadget);
return n;
}
static DEVICE_ATTR(srp, S_IWUSR, NULL, usb_udc_srp_store);
static ssize_t usb_udc_softconn_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t n)
{
struct usb_udc *udc = dev_get_drvdata(dev);
if (sysfs_streq(buf, "connect")) {
usb_gadget_connect(udc->gadget);
} else if (sysfs_streq(buf, "disconnect")) {
usb_gadget_disconnect(udc->gadget);
} else {
dev_err(dev, "unsupported command '%s'\n", buf);
return -EINVAL;
}
return n;
}
static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
static ssize_t usb_udc_speed_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
struct usb_gadget *gadget = udc->gadget;
switch (gadget->speed) {
case USB_SPEED_LOW:
return snprintf(buf, PAGE_SIZE, "low-speed\n");
case USB_SPEED_FULL:
return snprintf(buf, PAGE_SIZE, "full-speed\n");
case USB_SPEED_HIGH:
return snprintf(buf, PAGE_SIZE, "high-speed\n");
case USB_SPEED_WIRELESS:
return snprintf(buf, PAGE_SIZE, "wireless\n");
case USB_SPEED_SUPER:
return snprintf(buf, PAGE_SIZE, "super-speed\n");
case USB_SPEED_UNKNOWN: /* FALLTHROUGH */
default:
return snprintf(buf, PAGE_SIZE, "UNKNOWN\n");
}
}
static DEVICE_ATTR(speed, S_IRUSR, usb_udc_speed_show, NULL);
#define USB_UDC_ATTR(name) \
ssize_t usb_udc_##name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct usb_udc *udc = container_of(dev, struct usb_udc, dev); \
struct usb_gadget *gadget = udc->gadget; \
\
return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name); \
} \
static DEVICE_ATTR(name, S_IRUSR, usb_udc_##name##_show, NULL)
static USB_UDC_ATTR(is_dualspeed);
static USB_UDC_ATTR(is_otg);
static USB_UDC_ATTR(is_a_peripheral);
static USB_UDC_ATTR(b_hnp_enable);
static USB_UDC_ATTR(a_hnp_support);
static USB_UDC_ATTR(a_alt_hnp_support);
static struct attribute *usb_udc_attrs[] = {
&dev_attr_srp.attr,
&dev_attr_soft_connect.attr,
&dev_attr_speed.attr,
&dev_attr_is_dualspeed.attr,
&dev_attr_is_otg.attr,
&dev_attr_is_a_peripheral.attr,
&dev_attr_b_hnp_enable.attr,
&dev_attr_a_hnp_support.attr,
&dev_attr_a_alt_hnp_support.attr,
NULL,
};
static const struct attribute_group usb_udc_attr_group = {
.attrs = usb_udc_attrs,
};
static const struct attribute_group *usb_udc_attr_groups[] = {
&usb_udc_attr_group,
NULL,
};
static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
int ret;
ret = add_uevent_var(env, "USB_UDC_NAME=%s", udc->gadget->name);
if (ret) {
dev_err(dev, "failed to add uevent USB_UDC_NAME\n");
return ret;
}
if (udc->driver) {
ret = add_uevent_var(env, "USB_UDC_DRIVER=%s",
udc->driver->function);
if (ret) {
dev_err(dev, "failed to add uevent USB_UDC_DRIVER\n");
return ret;
}
}
return 0;
}
static int __init usb_udc_init(void)
{
udc_class = class_create(THIS_MODULE, "udc");
if (IS_ERR(udc_class)) {
pr_err("failed to create udc class --> %ld\n",
PTR_ERR(udc_class));
return PTR_ERR(udc_class);
}
udc_class->dev_uevent = usb_udc_uevent;
return 0;
}
subsys_initcall(usb_udc_init);
static void __exit usb_udc_exit(void)
{
class_destroy(udc_class);
}
module_exit(usb_udc_exit);
MODULE_DESCRIPTION("UDC Framework");
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("GPL v2");

Просмотреть файл

@ -373,6 +373,7 @@ static struct usb_composite_driver webcam_driver = {
.name = "g_webcam",
.dev = &webcam_device_descriptor,
.strings = webcam_device_strings,
.max_speed = USB_SPEED_HIGH,
.unbind = webcam_unbind,
};

Просмотреть файл

@ -340,6 +340,7 @@ static struct usb_composite_driver zero_driver = {
.name = "zero",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_SUPER,
.unbind = zero_unbind,
.suspend = zero_suspend,
.resume = zero_resume,

Просмотреть файл

@ -94,7 +94,8 @@ static const char hcd_name [] = "ehci_hcd";
#define EHCI_IAA_MSECS 10 /* arbitrary */
#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */
#define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1)
/* 200-ms async qh unlink delay */
/* Initial IRQ latency: faster than hw default */
static int log2_irq_thresh = 0; // 0 to 6
@ -114,7 +115,7 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
/* for link power management(LPM) feature */
static unsigned int hird;
module_param(hird, int, S_IRUGO);
MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n");
MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
@ -152,10 +153,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
break;
/* case TIMER_ASYNC_SHRINK: */
default:
/* add a jiffie since we synch against the
* 8 KHz uframe counter.
*/
t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
t = EHCI_SHRINK_JIFFIES;
break;
}
mod_timer(&ehci->watchdog, t + jiffies);
@ -340,6 +338,7 @@ static void ehci_work(struct ehci_hcd *ehci);
#include "ehci-mem.c"
#include "ehci-q.c"
#include "ehci-sched.c"
#include "ehci-sysfs.c"
/*-------------------------------------------------------------------------*/
@ -524,7 +523,7 @@ static void ehci_stop (struct usb_hcd *hcd)
ehci_reset (ehci);
spin_unlock_irq(&ehci->lock);
remove_companion_file(ehci);
remove_sysfs_files(ehci);
remove_debug_files (ehci);
/* root hub is shut down separately (first, when possible) */
@ -574,6 +573,12 @@ static int ehci_init(struct usb_hcd *hcd)
hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
/*
* by default set standard 80% (== 100 usec/uframe) max periodic
* bandwidth as required by USB 2.0
*/
ehci->uframe_periodic_max = 100;
/*
* hw default: 1K periodic list heads, one per frame.
* periodic_size can shrink by USBCMD update if hcc_params allows.
@ -758,7 +763,7 @@ static int ehci_run (struct usb_hcd *hcd)
* since the class device isn't created that early.
*/
create_debug_files(ehci);
create_companion_file(ehci);
create_sysfs_files(ehci);
return 0;
}

Просмотреть файл

@ -471,29 +471,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
/* Display the ports dedicated to the companion controller */
static ssize_t show_companion(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ehci_hcd *ehci;
int nports, index, n;
int count = PAGE_SIZE;
char *ptr = buf;
ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
nports = HCS_N_PORTS(ehci->hcs_params);
for (index = 0; index < nports; ++index) {
if (test_bit(index, &ehci->companion_ports)) {
n = scnprintf(ptr, count, "%d\n", index + 1);
ptr += n;
count -= n;
}
}
return ptr - buf;
}
/*
* Sets the owner of a port
*/
@ -528,58 +505,6 @@ static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner)
}
}
/*
* Dedicate or undedicate a port to the companion controller.
* Syntax is "[-]portnum", where a leading '-' sign means
* return control of the port to the EHCI controller.
*/
static ssize_t store_companion(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ehci_hcd *ehci;
int portnum, new_owner;
ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
new_owner = PORT_OWNER; /* Owned by companion */
if (sscanf(buf, "%d", &portnum) != 1)
return -EINVAL;
if (portnum < 0) {
portnum = - portnum;
new_owner = 0; /* Owned by EHCI */
}
if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
return -ENOENT;
portnum--;
if (new_owner)
set_bit(portnum, &ehci->companion_ports);
else
clear_bit(portnum, &ehci->companion_ports);
set_owner(ehci, portnum, new_owner);
return count;
}
static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
static inline int create_companion_file(struct ehci_hcd *ehci)
{
int i = 0;
/* with integrated TT there is no companion! */
if (!ehci_is_TDI(ehci))
i = device_create_file(ehci_to_hcd(ehci)->self.controller,
&dev_attr_companion);
return i;
}
static inline void remove_companion_file(struct ehci_hcd *ehci)
{
/* with integrated TT there is no companion! */
if (!ehci_is_TDI(ehci))
device_remove_file(ehci_to_hcd(ehci)->self.controller,
&dev_attr_companion);
}
/*-------------------------------------------------------------------------*/
static int check_reset_complete (
@ -891,10 +816,11 @@ static int ehci_hub_control (
* power switching; they're allowed to just limit the
* current. khubd will turn the power back on.
*/
if (HCS_PPC (ehci->hcs_params)){
if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) {
ehci_writel(ehci,
temp & ~(PORT_RWC_BITS | PORT_POWER),
status_reg);
temp = ehci_readl(ehci, status_reg);
}
}

Просмотреть файл

@ -40,27 +40,9 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
int retval;
ehci->caps = USB_CAPLENGTH;
ehci->regs = USB_CAPLENGTH +
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");
/* cache the data to minimize the chip reads*/
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
hcd->has_tt = 1;
ehci->sbrn = HCD_USB2;
retval = ehci_halt(ehci);
if (retval)
return retval;
/* data structure init */
retval = ehci_init(hcd);
if (retval)
return retval;
retval = ehci_reset(ehci);
retval = ehci_setup(hcd);
if (retval)
return retval;

Просмотреть файл

@ -103,7 +103,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
unsigned is_out, epnum;
is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
is_out = qh->is_out;
epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f;
if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
@ -946,6 +946,7 @@ done:
hw = qh->hw;
hw->hw_info1 = cpu_to_hc32(ehci, info1);
hw->hw_info2 = cpu_to_hc32(ehci, info2);
qh->is_out = !is_input;
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
qh_refresh (ehci, qh);
return qh;
@ -1231,6 +1232,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
prev->hw->hw_next = qh->hw->hw_next;
prev->qh_next = qh->qh_next;
if (ehci->qh_scan_next == qh)
ehci->qh_scan_next = qh->qh_next.qh;
wmb ();
/* If the controller isn't running, we don't have to wait for it */
@ -1256,53 +1259,49 @@ static void scan_async (struct ehci_hcd *ehci)
struct ehci_qh *qh;
enum ehci_timer_action action = TIMER_IO_WATCHDOG;
ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
timer_action_done (ehci, TIMER_ASYNC_SHRINK);
rescan:
stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
qh = ehci->async->qh_next.qh;
if (likely (qh != NULL)) {
do {
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list) && (stopped ||
qh->stamp != ehci->stamp)) {
int temp;
/* unlinks could happen here; completion
* reporting drops the lock. rescan using
* the latest schedule, but don't rescan
* qhs we already finished (no looping)
* unless the controller is stopped.
*/
qh = qh_get (qh);
qh->stamp = ehci->stamp;
temp = qh_completions (ehci, qh);
if (qh->needs_rescan)
unlink_async(ehci, qh);
qh_put (qh);
if (temp != 0) {
goto rescan;
}
}
ehci->qh_scan_next = ehci->async->qh_next.qh;
while (ehci->qh_scan_next) {
qh = ehci->qh_scan_next;
ehci->qh_scan_next = qh->qh_next.qh;
rescan:
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list)) {
int temp;
/* unlink idle entries, reducing DMA usage as well
* as HCD schedule-scanning costs. delay for any qh
* we just scanned, there's a not-unusual case that it
* doesn't stay idle for long.
* (plus, avoids some kind of re-activation race.)
/*
* Unlinks could happen here; completion reporting
* drops the lock. That's why ehci->qh_scan_next
* always holds the next qh to scan; if the next qh
* gets unlinked then ehci->qh_scan_next is adjusted
* in start_unlink_async().
*/
if (list_empty(&qh->qtd_list)
&& qh->qh_state == QH_STATE_LINKED) {
if (!ehci->reclaim && (stopped ||
((ehci->stamp - qh->stamp) & 0x1fff)
>= EHCI_SHRINK_FRAMES * 8))
start_unlink_async(ehci, qh);
else
action = TIMER_ASYNC_SHRINK;
}
qh = qh_get(qh);
temp = qh_completions(ehci, qh);
if (qh->needs_rescan)
unlink_async(ehci, qh);
qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
qh_put(qh);
if (temp != 0)
goto rescan;
}
qh = qh->qh_next.qh;
} while (qh);
/* unlink idle entries, reducing DMA usage as well
* as HCD schedule-scanning costs. delay for any qh
* we just scanned, there's a not-unusual case that it
* doesn't stay idle for long.
* (plus, avoids some kind of re-activation race.)
*/
if (list_empty(&qh->qtd_list)
&& qh->qh_state == QH_STATE_LINKED) {
if (!ehci->reclaim && (stopped ||
time_after_eq(jiffies, qh->unlink_time)))
start_unlink_async(ehci, qh);
else
action = TIMER_ASYNC_SHRINK;
}
}
if (action == TIMER_ASYNC_SHRINK)
timer_action (ehci, TIMER_ASYNC_SHRINK);

Просмотреть файл

@ -189,6 +189,100 @@ static void s5p_ehci_shutdown(struct platform_device *pdev)
hcd->driver->shutdown(hcd);
}
#ifdef CONFIG_PM
static int s5p_ehci_suspend(struct device *dev)
{
struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
struct usb_hcd *hcd = s5p_ehci->hcd;
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct platform_device *pdev = to_platform_device(dev);
struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
unsigned long flags;
int rc = 0;
if (time_before(jiffies, ehci->next_statechange))
msleep(20);
/*
* Root hub was already suspended. Disable irq emission and
* mark HW unaccessible. The PM and USB cores make sure that
* the root hub is either suspended or stopped.
*/
ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
spin_lock_irqsave(&ehci->lock, flags);
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
(void)ehci_readl(ehci, &ehci->regs->intr_enable);
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
spin_unlock_irqrestore(&ehci->lock, flags);
if (pdata && pdata->phy_exit)
pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
return rc;
}
static int s5p_ehci_resume(struct device *dev)
{
struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
struct usb_hcd *hcd = s5p_ehci->hcd;
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct platform_device *pdev = to_platform_device(dev);
struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
if (pdata && pdata->phy_init)
pdata->phy_init(pdev, S5P_USB_PHY_HOST);
if (time_before(jiffies, ehci->next_statechange))
msleep(100);
/* Mark hardware accessible again as we are out of D3 state by now */
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
int mask = INTR_MASK;
ehci_prepare_ports_for_controller_resume(ehci);
if (!hcd->self.root_hub->do_remote_wakeup)
mask &= ~STS_PCD;
ehci_writel(ehci, mask, &ehci->regs->intr_enable);
ehci_readl(ehci, &ehci->regs->intr_enable);
return 0;
}
usb_root_hub_lost_power(hcd->self.root_hub);
(void) ehci_halt(ehci);
(void) ehci_reset(ehci);
/* emptying the schedule aborts any urbs */
spin_lock_irq(&ehci->lock);
if (ehci->reclaim)
end_unlink_async(ehci);
ehci_work(ehci);
spin_unlock_irq(&ehci->lock);
ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
/* here we "know" root ports should always stay powered */
ehci_port_power(ehci, 1);
hcd->state = HC_STATE_SUSPENDED;
return 0;
}
#else
#define s5p_ehci_suspend NULL
#define s5p_ehci_resume NULL
#endif
static const struct dev_pm_ops s5p_ehci_pm_ops = {
.suspend = s5p_ehci_suspend,
.resume = s5p_ehci_resume,
};
static struct platform_driver s5p_ehci_driver = {
.probe = s5p_ehci_probe,
.remove = __devexit_p(s5p_ehci_remove),
@ -196,6 +290,7 @@ static struct platform_driver s5p_ehci_driver = {
.driver = {
.name = "s5p-ehci",
.owner = THIS_MODULE,
.pm = &s5p_ehci_pm_ops,
}
};

Просмотреть файл

@ -172,7 +172,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
}
}
#ifdef DEBUG
if (usecs > 100)
if (usecs > ehci->uframe_periodic_max)
ehci_err (ehci, "uframe %d sched overrun: %d usecs\n",
frame * 8 + uframe, usecs);
#endif
@ -709,11 +709,8 @@ static int check_period (
if (uframe >= 8)
return 0;
/*
* 80% periodic == 100 usec/uframe available
* convert "usecs we need" to "max already claimed"
*/
usecs = 100 - usecs;
/* convert "usecs we need" to "max already claimed" */
usecs = ehci->uframe_periodic_max - usecs;
/* we "know" 2 and 4 uframe intervals were rejected; so
* for period 0, check _every_ microframe in the schedule.
@ -1286,9 +1283,9 @@ itd_slot_ok (
{
uframe %= period;
do {
/* can't commit more than 80% periodic == 100 usec */
/* can't commit more than uframe_periodic_max usec */
if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
> (100 - usecs))
> (ehci->uframe_periodic_max - usecs))
return 0;
/* we know urb->interval is 2^N uframes */
@ -1345,7 +1342,7 @@ sitd_slot_ok (
#endif
/* check starts (OUT uses more than one) */
max_used = 100 - stream->usecs;
max_used = ehci->uframe_periodic_max - stream->usecs;
for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {
if (periodic_usecs (ehci, frame, uf) > max_used)
return 0;
@ -1354,7 +1351,7 @@ sitd_slot_ok (
/* for IN, check CSPLIT */
if (stream->c_usecs) {
uf = uframe & 7;
max_used = 100 - stream->c_usecs;
max_used = ehci->uframe_periodic_max - stream->c_usecs;
do {
tmp = 1 << uf;
tmp <<= 8;

Просмотреть файл

@ -0,0 +1,190 @@
/*
* Copyright (C) 2007 by Alan Stern
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* this file is part of ehci-hcd.c */
/* Display the ports dedicated to the companion controller */
static ssize_t show_companion(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ehci_hcd *ehci;
int nports, index, n;
int count = PAGE_SIZE;
char *ptr = buf;
ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
nports = HCS_N_PORTS(ehci->hcs_params);
for (index = 0; index < nports; ++index) {
if (test_bit(index, &ehci->companion_ports)) {
n = scnprintf(ptr, count, "%d\n", index + 1);
ptr += n;
count -= n;
}
}
return ptr - buf;
}
/*
* Dedicate or undedicate a port to the companion controller.
* Syntax is "[-]portnum", where a leading '-' sign means
* return control of the port to the EHCI controller.
*/
static ssize_t store_companion(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ehci_hcd *ehci;
int portnum, new_owner;
ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
new_owner = PORT_OWNER; /* Owned by companion */
if (sscanf(buf, "%d", &portnum) != 1)
return -EINVAL;
if (portnum < 0) {
portnum = - portnum;
new_owner = 0; /* Owned by EHCI */
}
if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
return -ENOENT;
portnum--;
if (new_owner)
set_bit(portnum, &ehci->companion_ports);
else
clear_bit(portnum, &ehci->companion_ports);
set_owner(ehci, portnum, new_owner);
return count;
}
static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
/*
* Display / Set uframe_periodic_max
*/
static ssize_t show_uframe_periodic_max(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ehci_hcd *ehci;
int n;
ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max);
return n;
}
static ssize_t store_uframe_periodic_max(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ehci_hcd *ehci;
unsigned uframe_periodic_max;
unsigned frame, uframe;
unsigned short allocated_max;
unsigned long flags;
ssize_t ret;
ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
return -EINVAL;
if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
ehci_info(ehci, "rejecting invalid request for "
"uframe_periodic_max=%u\n", uframe_periodic_max);
return -EINVAL;
}
ret = -EINVAL;
/*
* lock, so that our checking does not race with possible periodic
* bandwidth allocation through submitting new urbs.
*/
spin_lock_irqsave (&ehci->lock, flags);
/*
* for request to decrease max periodic bandwidth, we have to check
* every microframe in the schedule to see whether the decrease is
* possible.
*/
if (uframe_periodic_max < ehci->uframe_periodic_max) {
allocated_max = 0;
for (frame = 0; frame < ehci->periodic_size; ++frame)
for (uframe = 0; uframe < 7; ++uframe)
allocated_max = max(allocated_max,
periodic_usecs (ehci, frame, uframe));
if (allocated_max > uframe_periodic_max) {
ehci_info(ehci,
"cannot decrease uframe_periodic_max becase "
"periodic bandwidth is already allocated "
"(%u > %u)\n",
allocated_max, uframe_periodic_max);
goto out_unlock;
}
}
/* increasing is always ok */
ehci_info(ehci, "setting max periodic bandwidth to %u%% "
"(== %u usec/uframe)\n",
100*uframe_periodic_max/125, uframe_periodic_max);
if (uframe_periodic_max != 100)
ehci_warn(ehci, "max periodic bandwidth set is non-standard\n");
ehci->uframe_periodic_max = uframe_periodic_max;
ret = count;
out_unlock:
spin_unlock_irqrestore (&ehci->lock, flags);
return ret;
}
static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max);
static inline int create_sysfs_files(struct ehci_hcd *ehci)
{
struct device *controller = ehci_to_hcd(ehci)->self.controller;
int i = 0;
/* with integrated TT there is no companion! */
if (!ehci_is_TDI(ehci))
i = device_create_file(controller, &dev_attr_companion);
if (i)
goto out;
i = device_create_file(controller, &dev_attr_uframe_periodic_max);
out:
return i;
}
static inline void remove_sysfs_files(struct ehci_hcd *ehci)
{
struct device *controller = ehci_to_hcd(ehci)->self.controller;
/* with integrated TT there is no companion! */
if (!ehci_is_TDI(ehci))
device_remove_file(controller, &dev_attr_companion);
device_remove_file(controller, &dev_attr_uframe_periodic_max);
}

Просмотреть файл

@ -75,6 +75,7 @@ struct ehci_hcd { /* one per controller */
struct ehci_qh *async;
struct ehci_qh *dummy; /* For AMD quirk use */
struct ehci_qh *reclaim;
struct ehci_qh *qh_scan_next;
unsigned scanning : 1;
/* periodic schedule support */
@ -87,6 +88,8 @@ struct ehci_hcd { /* one per controller */
union ehci_shadow *pshadow; /* mirror hw periodic table */
int next_uframe; /* scan periodic, start here */
unsigned periodic_sched; /* periodic activity count */
unsigned uframe_periodic_max; /* max periodic time per uframe */
/* list of itds & sitds completed while clock_frame was still active */
struct list_head cached_itd_list;
@ -117,7 +120,6 @@ struct ehci_hcd { /* one per controller */
struct timer_list iaa_watchdog;
struct timer_list watchdog;
unsigned long actions;
unsigned stamp;
unsigned periodic_stamp;
unsigned random_frame;
unsigned long next_statechange;
@ -343,6 +345,7 @@ struct ehci_qh {
struct ehci_qh *reclaim; /* next to reclaim */
struct ehci_hcd *ehci;
unsigned long unlink_time;
/*
* Do NOT use atomic operations for QH refcounting. On some CPUs
@ -374,6 +377,7 @@ struct ehci_qh {
#define NO_FRAME ((unsigned short)~0) /* pick new start */
struct usb_device *dev; /* access to TT */
unsigned is_out:1; /* bulk or intr OUT */
unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
};

Просмотреть файл

@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Renesas Solutions Corp.
*
* Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
* Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

Просмотреть файл

@ -35,6 +35,8 @@
#define OHCI_INTRSTATUS 0x0c
#define OHCI_INTRENABLE 0x10
#define OHCI_INTRDISABLE 0x14
#define OHCI_FMINTERVAL 0x34
#define OHCI_HCR (1 << 0) /* host controller reset */
#define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
@ -497,6 +499,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
/* reset controller, preserving RWC (and possibly IR) */
writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
readl(base + OHCI_CONTROL);
/* Some NVIDIA controllers stop working if kept in RESET for too long */
if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
u32 fminterval;
int cnt;
/* drive reset for at least 50 ms (7.1.7.5) */
msleep(50);
/* software reset of the controller, preserving HcFmInterval */
fminterval = readl(base + OHCI_FMINTERVAL);
writel(OHCI_HCR, base + OHCI_CMDSTATUS);
/* reset requires max 10 us delay */
for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */
if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
break;
udelay(1);
}
writel(fminterval, base + OHCI_FMINTERVAL);
/* Now we're in the SUSPEND state with all devices reset
* and wakeups and interrupts disabled
*/
}
/*
* disable interrupts
@ -507,20 +535,34 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
iounmap(base);
}
static const struct dmi_system_id __initconst ehci_dmi_nohandoff_table[] = {
{
/* Pegatron Lucid (ExoPC) */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "EXOPG06411"),
DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"),
},
},
{
/* Pegatron Lucid (Ordissimo AIRIS) */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
},
},
{ }
};
static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
void __iomem *op_reg_base,
u32 cap, u8 offset)
{
int try_handoff = 1, tried_handoff = 0;
/* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90
* seconds trying the handoff on its unused controller. Skip
* it. */
/* The Pegatron Lucid tablet sporadically waits for 98 seconds trying
* the handoff on its unused controller. Skip it. */
if (pdev->vendor == 0x8086 && pdev->device == 0x283a) {
const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME);
const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION);
if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") &&
dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133"))
if (dmi_check_system(ehci_dmi_nohandoff_table))
try_handoff = 0;
}

Просмотреть файл

@ -6,7 +6,7 @@
* Portions Copyright (C) 2004-2005 David Brownell
* Portions Copyright (C) 1999 Roman Weissgaerber
*
* Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
* Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -1438,7 +1438,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
if (pipenum > 0)
r8a66597_write(r8a66597, ~(1 << pipenum), BEMPSTS);
if (urb->transfer_buffer) {
r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size);
r8a66597_write_fifo(r8a66597, td->pipe, buf, size);
if (!usb_pipebulk(urb->pipe) || td->maxpacket != size)
r8a66597_write(r8a66597, BVAL, td->pipe->fifoctr);
}
@ -2306,7 +2306,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
dbg("resume port = %d", port);
rh->port &= ~USB_PORT_STAT_SUSPEND;
rh->port |= USB_PORT_STAT_C_SUSPEND < 16;
rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
msleep(50);
r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);

Просмотреть файл

@ -201,11 +201,26 @@ static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
iowrite16(val, r8a66597->reg + offset);
}
static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
u16 val, u16 pat, unsigned long offset)
{
u16 tmp;
tmp = r8a66597_read(r8a66597, offset);
tmp = tmp & (~pat);
tmp = tmp | val;
r8a66597_write(r8a66597, tmp, offset);
}
#define r8a66597_bclr(r8a66597, val, offset) \
r8a66597_mdfy(r8a66597, 0, val, offset)
#define r8a66597_bset(r8a66597, val, offset) \
r8a66597_mdfy(r8a66597, val, 0, offset)
static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
unsigned long offset, u16 *buf,
struct r8a66597_pipe *pipe, u16 *buf,
int len)
{
void __iomem *fifoaddr = r8a66597->reg + offset;
void __iomem *fifoaddr = r8a66597->reg + pipe->fifoaddr;
unsigned long count;
unsigned char *pb;
int i;
@ -230,26 +245,15 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
iowrite16_rep(fifoaddr, buf, len);
if (unlikely(odd)) {
buf = &buf[len];
if (r8a66597->pdata->wr0_shorted_to_wr1)
r8a66597_bclr(r8a66597, MBW_16, pipe->fifosel);
iowrite8((unsigned char)*buf, fifoaddr);
if (r8a66597->pdata->wr0_shorted_to_wr1)
r8a66597_bset(r8a66597, MBW_16, pipe->fifosel);
}
}
}
static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
u16 val, u16 pat, unsigned long offset)
{
u16 tmp;
tmp = r8a66597_read(r8a66597, offset);
tmp = tmp & (~pat);
tmp = tmp | val;
r8a66597_write(r8a66597, tmp, offset);
}
#define r8a66597_bclr(r8a66597, val, offset) \
r8a66597_mdfy(r8a66597, 0, val, offset)
#define r8a66597_bset(r8a66597, val, offset) \
r8a66597_mdfy(r8a66597, val, 0, offset)
static inline unsigned long get_syscfg_reg(int port)
{
return port == 0 ? SYSCFG0 : SYSCFG1;

Просмотреть файл

@ -266,11 +266,11 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
xhci_dbg(xhci, "Interrupter target = 0x%x\n",
GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target)));
xhci_dbg(xhci, "Cycle bit = %u\n",
(unsigned int) (le32_to_cpu(trb->link.control) & TRB_CYCLE));
le32_to_cpu(trb->link.control) & TRB_CYCLE);
xhci_dbg(xhci, "Toggle cycle bit = %u\n",
(unsigned int) (le32_to_cpu(trb->link.control) & LINK_TOGGLE));
le32_to_cpu(trb->link.control) & LINK_TOGGLE);
xhci_dbg(xhci, "No Snoop bit = %u\n",
(unsigned int) (le32_to_cpu(trb->link.control) & TRB_NO_SNOOP));
le32_to_cpu(trb->link.control) & TRB_NO_SNOOP);
break;
case TRB_TYPE(TRB_TRANSFER):
address = le64_to_cpu(trb->trans_event.buffer);
@ -284,9 +284,9 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
address = le64_to_cpu(trb->event_cmd.cmd_trb);
xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
xhci_dbg(xhci, "Completion status = %u\n",
(unsigned int) GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
xhci_dbg(xhci, "Flags = 0x%x\n",
(unsigned int) le32_to_cpu(trb->event_cmd.flags));
le32_to_cpu(trb->event_cmd.flags));
break;
default:
xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n",
@ -318,10 +318,10 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
trb = &seg->trbs[i];
xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr,
(u32)lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
(u32)upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
(unsigned int) le32_to_cpu(trb->link.intr_target),
(unsigned int) le32_to_cpu(trb->link.control));
lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
le32_to_cpu(trb->link.intr_target),
le32_to_cpu(trb->link.control));
addr += sizeof(*trb);
}
}
@ -402,8 +402,8 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
addr,
lower_32_bits(le64_to_cpu(entry->seg_addr)),
upper_32_bits(le64_to_cpu(entry->seg_addr)),
(unsigned int) le32_to_cpu(entry->seg_size),
(unsigned int) le32_to_cpu(entry->rsvd));
le32_to_cpu(entry->seg_size),
le32_to_cpu(entry->rsvd));
addr += sizeof(*entry);
}
}

Просмотреть файл

@ -89,8 +89,8 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
prev->trbs[TRBS_PER_SEGMENT-1].link.
segment_ptr = cpu_to_le64(next->dma);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(next->dma);
/* Set the last TRB in the segment to have a TRB type ID of Link TRB */
val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control);
@ -187,8 +187,8 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.
control |= cpu_to_le32(LINK_TOGGLE);
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
cpu_to_le32(LINK_TOGGLE);
xhci_dbg(xhci, "Wrote link toggle flag to"
" segment %p (virtual), 0x%llx (DMA)\n",
prev, (unsigned long long)prev->dma);
@ -549,8 +549,8 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
addr = cur_ring->first_seg->dma |
SCT_FOR_CTX(SCT_PRI_TR) |
cur_ring->cycle_state;
stream_info->stream_ctx_array[cur_stream].
stream_ring = cpu_to_le64(addr);
stream_info->stream_ctx_array[cur_stream].stream_ring =
cpu_to_le64(addr);
xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n",
cur_stream, (unsigned long long) addr);
@ -786,7 +786,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
slot_id,
&xhci->dcbaa->dev_context_ptrs[slot_id],
(unsigned long long) le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
return 1;
fail:
@ -890,19 +890,19 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
/* 3) Only the control endpoint is valid - one endpoint context */
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | (u32) udev->route);
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);
switch (udev->speed) {
case USB_SPEED_SUPER:
slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_SS);
slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS);
break;
case USB_SPEED_HIGH:
slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_HS);
slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS);
break;
case USB_SPEED_FULL:
slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_FS);
slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS);
break;
case USB_SPEED_LOW:
slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_LS);
slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS);
break;
case USB_SPEED_WIRELESS:
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
@ -916,7 +916,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
port_num = xhci_find_real_port_number(xhci, udev);
if (!port_num)
return -EINVAL;
slot_ctx->dev_info2 |= cpu_to_le32((u32) ROOT_HUB_PORT(port_num));
slot_ctx->dev_info2 |= cpu_to_le32(ROOT_HUB_PORT(port_num));
/* Set the port number in the virtual_device to the faked port number */
for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
top_dev = top_dev->parent)

Просмотреть файл

@ -113,15 +113,13 @@ static int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
if (ring == xhci->event_ring)
return trb == &seg->trbs[TRBS_PER_SEGMENT];
else
return (le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK)
== TRB_TYPE(TRB_LINK);
return TRB_TYPE_LINK_LE32(trb->link.control);
}
static int enqueue_is_link_trb(struct xhci_ring *ring)
{
struct xhci_link_trb *link = &ring->enqueue->link;
return ((le32_to_cpu(link->control) & TRB_TYPE_BITMASK) ==
TRB_TYPE(TRB_LINK));
return TRB_TYPE_LINK_LE32(link->control);
}
/* Updates trb to point to the next TRB in the ring, and updates seg if the next
@ -372,7 +370,7 @@ static struct xhci_segment *find_trb_seg(
while (cur_seg->trbs > trb ||
&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
if (le32_to_cpu(generic_trb->field[3]) & LINK_TOGGLE)
if (generic_trb->field[3] & cpu_to_le32(LINK_TOGGLE))
*cycle_state ^= 0x1;
cur_seg = cur_seg->next;
if (cur_seg == start_seg)
@ -489,8 +487,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
}
trb = &state->new_deq_ptr->generic;
if ((le32_to_cpu(trb->field[3]) & TRB_TYPE_BITMASK) ==
TRB_TYPE(TRB_LINK) && (le32_to_cpu(trb->field[3]) & LINK_TOGGLE))
if (TRB_TYPE_LINK_LE32(trb->field[3]) &&
(trb->field[3] & cpu_to_le32(LINK_TOGGLE)))
state->new_cycle_state ^= 0x1;
next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
@ -525,8 +523,7 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
for (cur_seg = cur_td->start_seg, cur_trb = cur_td->first_trb;
true;
next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
if ((le32_to_cpu(cur_trb->generic.field[3]) & TRB_TYPE_BITMASK)
== TRB_TYPE(TRB_LINK)) {
if (TRB_TYPE_LINK_LE32(cur_trb->generic.field[3])) {
/* Unchain any chained Link TRBs, but
* leave the pointers intact.
*/
@ -1000,7 +997,7 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
* but we don't care.
*/
xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
(unsigned int) GET_COMP_CODE(le32_to_cpu(event->status)));
GET_COMP_CODE(le32_to_cpu(event->status)));
/* HW with the reset endpoint quirk needs to have a configure endpoint
* command complete before the endpoint can be used. Queue that here
@ -1458,7 +1455,8 @@ static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci,
* endpoint anyway. Check if a babble halted the
* endpoint.
*/
if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED)
if ((ep_ctx->ep_info & cpu_to_le32(EP_STATE_MASK)) ==
cpu_to_le32(EP_STATE_HALTED))
return 1;
return 0;
@ -1753,10 +1751,8 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
for (cur_trb = ep_ring->dequeue,
cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
if ((le32_to_cpu(cur_trb->generic.field[3]) &
TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
(le32_to_cpu(cur_trb->generic.field[3]) &
TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
if (!TRB_TYPE_NOOP_LE32(cur_trb->generic.field[3]) &&
!TRB_TYPE_LINK_LE32(cur_trb->generic.field[3]))
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
}
len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
@ -1885,10 +1881,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
cur_trb != event_trb;
next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
if ((le32_to_cpu(cur_trb->generic.field[3]) &
TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
(le32_to_cpu(cur_trb->generic.field[3]) &
TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
if (!TRB_TYPE_NOOP_LE32(cur_trb->generic.field[3]) &&
!TRB_TYPE_LINK_LE32(cur_trb->generic.field[3]))
td->urb->actual_length +=
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
}
@ -2047,8 +2041,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
ep_index);
xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
(unsigned int) (le32_to_cpu(event->flags)
& TRB_TYPE_BITMASK)>>10);
(le32_to_cpu(event->flags) &
TRB_TYPE_BITMASK)>>10);
xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
if (ep->skip) {
ep->skip = false;
@ -2119,9 +2113,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* corresponding TD has been cancelled. Just ignore
* the TD.
*/
if ((le32_to_cpu(event_trb->generic.field[3])
& TRB_TYPE_BITMASK)
== TRB_TYPE(TRB_TR_NOOP)) {
if (TRB_TYPE_NOOP_LE32(event_trb->generic.field[3])) {
xhci_dbg(xhci,
"event_trb is a no-op TRB. Skip it\n");
goto cleanup;
@ -2452,7 +2444,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
next->link.control |= cpu_to_le32(TRB_CHAIN);
wmb();
next->link.control ^= cpu_to_le32((u32) TRB_CYCLE);
next->link.control ^= cpu_to_le32(TRB_CYCLE);
/* Toggle the cycle bit after the last ring segment. */
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {

Просмотреть файл

@ -1342,8 +1342,8 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
/* If the HC already knows the endpoint is disabled,
* or the HCD has noted it is disabled, ignore this request
*/
if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
EP_STATE_DISABLED ||
if (((ep_ctx->ep_info & cpu_to_le32(EP_STATE_MASK)) ==
cpu_to_le32(EP_STATE_DISABLED)) ||
le32_to_cpu(ctrl_ctx->drop_flags) &
xhci_get_endpoint_flag(&ep->desc)) {
xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
@ -1758,8 +1758,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
/* Enqueue pointer can be left pointing to the link TRB,
* we must handle that
*/
if ((le32_to_cpu(command->command_trb->link.control)
& TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
if (TRB_TYPE_LINK_LE32(command->command_trb->link.control))
command->command_trb =
xhci->cmd_ring->enq_seg->next->trbs;
@ -2559,8 +2558,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
/* Enqueue pointer can be left pointing to the link TRB,
* we must handle that
*/
if ((le32_to_cpu(reset_device_cmd->command_trb->link.control)
& TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
if (TRB_TYPE_LINK_LE32(reset_device_cmd->command_trb->link.control))
reset_device_cmd->command_trb =
xhci->cmd_ring->enq_seg->next->trbs;

Просмотреть файл

@ -1072,6 +1072,13 @@ union xhci_trb {
/* Get NEC firmware revision. */
#define TRB_NEC_GET_FW 49
#define TRB_TYPE_LINK(x) (((x) & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
/* Above, but for __le32 types -- can avoid work by swapping constants: */
#define TRB_TYPE_LINK_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \
cpu_to_le32(TRB_TYPE(TRB_LINK)))
#define TRB_TYPE_NOOP_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \
cpu_to_le32(TRB_TYPE(TRB_TR_NOOP)))
#define NEC_FW_MINOR(p) (((p) >> 0) & 0xff)
#define NEC_FW_MAJOR(p) (((p) >> 8) & 0xff)

Просмотреть файл

@ -670,6 +670,9 @@ int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
int busnum = ubus? ubus->busnum: 0;
int rc;
if (mon_dir == NULL)
return 0;
if (ubus != NULL) {
rc = snprintf(name, NAMESZ, "%dt", busnum);
if (rc <= 0 || rc >= NAMESZ)
@ -740,12 +743,12 @@ int __init mon_text_init(void)
mondir = debugfs_create_dir("usbmon", usb_debug_root);
if (IS_ERR(mondir)) {
printk(KERN_NOTICE TAG ": debugfs is not available\n");
return -ENODEV;
/* debugfs not available, but we can use usbmon without it */
return 0;
}
if (mondir == NULL) {
printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
return -ENODEV;
return -ENOMEM;
}
mon_dir = mondir;
return 0;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше