usb: patches for v3.17 merge window
Surprisingly enough, while a big set of patches, the majority is composed of cleanups (using devm_*, fixing sparse errors, moving code around, adding const, etc). The highlights are addition of new support for PLX USB338x devices, and support for USB 2.0-only configurations of the DWC3 IP core. Signed-of-by: Felipe Balbi <balbi@ti.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTzTI9AAoJEIaOsuA1yqREIqcQAJbwMaDb5sp8dWst+nL1Vo8N 08bhOOM+o2KLiIBSNQh1hYtujpa06RSQMiNYZ7F/+R4Q3OAoq+uC0dD69TLEQ3Sd 1xi0UgUTAvtXo13TToRjIi0mYywrrkZ91Maqff5jZKdslOY4ZfAScpUQHyD3i1UO JNUqpayYAnp8JJIGQ8CG1wAeJh/J8JH3O607vaknKVjds+WMkeC5ubnuV4sgVw71 8JTwxk22EkMTr2MKhHjZwcv016NMEvziinWVoTXcWN2Uwk42Dn1nhfaYWSvg7kZE 8/3t6zzdFMdoeeTEn2xXIQGTjbHW0sBS5+S+6PAon2YbjS3x40cbyLJnZ+KoVXog iHDKAl5w53gd/7qMiv57dW+HRP0M7/m2iy/owIrY8H8DkM3uwFevaeq/G2raJKmA frB1k95bSyypN7wVkALYv4nurP5+d7ERy9hPj/49M5giJXPpEIbgKN2qGdafaEx7 xzAI+GqYrFtmmg25+f6AQRicVczQNMCdDT8HPZ04099Z2JVY/4uOoqTl29CePMgo OXeQ45ECMoJuRSwpF56e8h+qmsXp6WD31IhlcHseTvUvFu0Ex4SgUJhFP2UaF9WP aOqz0w36yX/ME3VhQk9YImNqGoqEk6fYHIHhxfdDugt0n68+M56EiiwtKvd5v5BI hCJAMBrv+WCGnJvWunVW =aJY4 -----END PGP SIGNATURE----- Merge tag 'usb-for-v3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next Felipe writes: usb: patches for v3.17 merge window Surprisingly enough, while a big set of patches, the majority is composed of cleanups (using devm_*, fixing sparse errors, moving code around, adding const, etc). The highlights are addition of new support for PLX USB338x devices, and support for USB 2.0-only configurations of the DWC3 IP core. Signed-of-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
commit
61fe2d75f1
|
@ -556,11 +556,11 @@ been converted to this framework.
|
|||
Near-term plans include converting all of them, except for "gadgetfs".
|
||||
</para>
|
||||
|
||||
!Edrivers/usb/gadget/f_acm.c
|
||||
!Edrivers/usb/gadget/f_ecm.c
|
||||
!Edrivers/usb/gadget/f_subset.c
|
||||
!Edrivers/usb/gadget/f_obex.c
|
||||
!Edrivers/usb/gadget/f_serial.c
|
||||
!Edrivers/usb/gadget/function/f_acm.c
|
||||
!Edrivers/usb/gadget/function/f_ecm.c
|
||||
!Edrivers/usb/gadget/function/f_subset.c
|
||||
!Edrivers/usb/gadget/function/f_obex.c
|
||||
!Edrivers/usb/gadget/function/f_serial.c
|
||||
|
||||
</sect1>
|
||||
|
||||
|
|
|
@ -386,6 +386,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
|||
}
|
||||
dwc->revision = reg;
|
||||
|
||||
/* Handle USB2.0-only core configuration */
|
||||
if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) ==
|
||||
DWC3_GHWPARAMS3_SSPHY_IFC_DIS) {
|
||||
if (dwc->maximum_speed == USB_SPEED_SUPER)
|
||||
dwc->maximum_speed = USB_SPEED_HIGH;
|
||||
}
|
||||
|
||||
/* issue device SoftReset too */
|
||||
timeout = jiffies + msecs_to_jiffies(500);
|
||||
dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
|
||||
|
@ -656,6 +663,31 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
dwc->xhci_resources[0].start = res->start;
|
||||
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
|
||||
DWC3_XHCI_REGS_END;
|
||||
dwc->xhci_resources[0].flags = res->flags;
|
||||
dwc->xhci_resources[0].name = res->name;
|
||||
|
||||
res->start += DWC3_GLOBALS_REGS_START;
|
||||
|
||||
/*
|
||||
* Request memory region but exclude xHCI regs,
|
||||
* since it will be requested by the xhci-plat driver.
|
||||
*/
|
||||
regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
dwc->regs = regs;
|
||||
dwc->regs_size = resource_size(res);
|
||||
/*
|
||||
* restore res->start back to its original value so that,
|
||||
* in case the probe is deferred, we don't end up getting error in
|
||||
* request the memory region the next time probe is called.
|
||||
*/
|
||||
res->start -= DWC3_GLOBALS_REGS_START;
|
||||
|
||||
if (node) {
|
||||
dwc->maximum_speed = of_usb_get_maximum_speed(node);
|
||||
|
||||
|
@ -676,28 +708,9 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
dwc->xhci_resources[0].start = res->start;
|
||||
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
|
||||
DWC3_XHCI_REGS_END;
|
||||
dwc->xhci_resources[0].flags = res->flags;
|
||||
dwc->xhci_resources[0].name = res->name;
|
||||
|
||||
res->start += DWC3_GLOBALS_REGS_START;
|
||||
|
||||
/*
|
||||
* Request memory region but exclude xHCI regs,
|
||||
* since it will be requested by the xhci-plat driver.
|
||||
*/
|
||||
regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
|
||||
spin_lock_init(&dwc->lock);
|
||||
platform_set_drvdata(pdev, dwc);
|
||||
|
||||
dwc->regs = regs;
|
||||
dwc->regs_size = resource_size(res);
|
||||
|
||||
dev->dma_mask = dev->parent->dma_mask;
|
||||
dev->dma_parms = dev->parent->dma_parms;
|
||||
dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
|
||||
|
|
|
@ -191,6 +191,19 @@
|
|||
#define DWC3_GHWPARAMS1_PWROPT(n) ((n) << 24)
|
||||
#define DWC3_GHWPARAMS1_PWROPT_MASK DWC3_GHWPARAMS1_PWROPT(3)
|
||||
|
||||
/* Global HWPARAMS3 Register */
|
||||
#define DWC3_GHWPARAMS3_SSPHY_IFC(n) ((n) & 3)
|
||||
#define DWC3_GHWPARAMS3_SSPHY_IFC_DIS 0
|
||||
#define DWC3_GHWPARAMS3_SSPHY_IFC_ENA 1
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC(n) (((n) & (3 << 2)) >> 2)
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC_DIS 0
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI 1
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC_ULPI 2
|
||||
#define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI 3
|
||||
#define DWC3_GHWPARAMS3_FSPHY_IFC(n) (((n) & (3 << 4)) >> 4)
|
||||
#define DWC3_GHWPARAMS3_FSPHY_IFC_DIS 0
|
||||
#define DWC3_GHWPARAMS3_FSPHY_IFC_ENA 1
|
||||
|
||||
/* Global HWPARAMS4 Register */
|
||||
#define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) & (0x0f << 13)) >> 13)
|
||||
#define DWC3_MAX_HIBER_SCRATCHBUFS 15
|
||||
|
|
|
@ -77,10 +77,6 @@
|
|||
#define USBOTGSS_DEV_EBC_EN 0x0110
|
||||
#define USBOTGSS_DEBUG_OFFSET 0x0600
|
||||
|
||||
/* REVISION REGISTER */
|
||||
#define USBOTGSS_REVISION_XMAJOR(reg) ((reg >> 8) & 0x7)
|
||||
#define USBOTGSS_REVISION_XMAJOR1 1
|
||||
#define USBOTGSS_REVISION_XMAJOR2 2
|
||||
/* SYSCONFIG REGISTER */
|
||||
#define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16)
|
||||
|
||||
|
@ -129,7 +125,6 @@ struct dwc3_omap {
|
|||
u32 irq_eoi_offset;
|
||||
u32 debug_offset;
|
||||
u32 irq0_offset;
|
||||
u32 revision;
|
||||
|
||||
u32 dma_status:1;
|
||||
|
||||
|
@ -383,6 +378,87 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static void dwc3_omap_map_offset(struct dwc3_omap *omap)
|
||||
{
|
||||
struct device_node *node = omap->dev->of_node;
|
||||
|
||||
/*
|
||||
* Differentiate between OMAP5 and AM437x.
|
||||
*
|
||||
* For OMAP5(ES2.0) and AM437x wrapper revision is same, even
|
||||
* though there are changes in wrapper register offsets.
|
||||
*
|
||||
* Using dt compatible to differentiate AM437x.
|
||||
*/
|
||||
if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
|
||||
omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
|
||||
omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
|
||||
omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
|
||||
omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
|
||||
omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
|
||||
}
|
||||
}
|
||||
|
||||
static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
|
||||
{
|
||||
u32 reg;
|
||||
struct device_node *node = omap->dev->of_node;
|
||||
int utmi_mode = 0;
|
||||
|
||||
reg = dwc3_omap_read_utmi_status(omap);
|
||||
|
||||
of_property_read_u32(node, "utmi-mode", &utmi_mode);
|
||||
|
||||
switch (utmi_mode) {
|
||||
case DWC3_OMAP_UTMI_MODE_SW:
|
||||
reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
|
||||
break;
|
||||
case DWC3_OMAP_UTMI_MODE_HW:
|
||||
reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
|
||||
}
|
||||
|
||||
dwc3_omap_write_utmi_status(omap, reg);
|
||||
}
|
||||
|
||||
static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
|
||||
{
|
||||
u32 ret;
|
||||
struct device_node *node = omap->dev->of_node;
|
||||
struct extcon_dev *edev;
|
||||
|
||||
if (of_property_read_bool(node, "extcon")) {
|
||||
edev = extcon_get_edev_by_phandle(omap->dev, 0);
|
||||
if (IS_ERR(edev)) {
|
||||
dev_vdbg(omap->dev, "couldn't get extcon device\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
|
||||
ret = extcon_register_interest(&omap->extcon_vbus_dev,
|
||||
edev->name, "USB",
|
||||
&omap->vbus_nb);
|
||||
if (ret < 0)
|
||||
dev_vdbg(omap->dev, "failed to register notifier for USB\n");
|
||||
|
||||
omap->id_nb.notifier_call = dwc3_omap_id_notifier;
|
||||
ret = extcon_register_interest(&omap->extcon_id_dev,
|
||||
edev->name, "USB-HOST",
|
||||
&omap->id_nb);
|
||||
if (ret < 0)
|
||||
dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
|
||||
|
||||
if (extcon_get_cable_state(edev, "USB") == true)
|
||||
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
|
||||
if (extcon_get_cable_state(edev, "USB-HOST") == true)
|
||||
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwc3_omap_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
@ -390,15 +466,11 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
|||
struct dwc3_omap *omap;
|
||||
struct resource *res;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct extcon_dev *edev;
|
||||
struct regulator *vbus_reg = NULL;
|
||||
|
||||
int ret;
|
||||
int irq;
|
||||
|
||||
int utmi_mode = 0;
|
||||
int x_major;
|
||||
|
||||
u32 reg;
|
||||
|
||||
void __iomem *base;
|
||||
|
@ -448,58 +520,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
|||
goto err0;
|
||||
}
|
||||
|
||||
reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION);
|
||||
omap->revision = reg;
|
||||
x_major = USBOTGSS_REVISION_XMAJOR(reg);
|
||||
|
||||
/* Differentiate between OMAP5 and AM437x */
|
||||
switch (x_major) {
|
||||
case USBOTGSS_REVISION_XMAJOR1:
|
||||
case USBOTGSS_REVISION_XMAJOR2:
|
||||
omap->irq_eoi_offset = 0;
|
||||
omap->irq0_offset = 0;
|
||||
omap->irqmisc_offset = 0;
|
||||
omap->utmi_otg_offset = 0;
|
||||
omap->debug_offset = 0;
|
||||
break;
|
||||
default:
|
||||
/* Default to the latest revision */
|
||||
omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
|
||||
omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
|
||||
omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
|
||||
omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
|
||||
omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
|
||||
break;
|
||||
}
|
||||
|
||||
/* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are
|
||||
* changes in wrapper registers, Using dt compatible for aegis
|
||||
*/
|
||||
|
||||
if (of_device_is_compatible(node, "ti,am437x-dwc3")) {
|
||||
omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET;
|
||||
omap->irq0_offset = USBOTGSS_IRQ0_OFFSET;
|
||||
omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET;
|
||||
omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET;
|
||||
omap->debug_offset = USBOTGSS_DEBUG_OFFSET;
|
||||
}
|
||||
|
||||
reg = dwc3_omap_read_utmi_status(omap);
|
||||
|
||||
of_property_read_u32(node, "utmi-mode", &utmi_mode);
|
||||
|
||||
switch (utmi_mode) {
|
||||
case DWC3_OMAP_UTMI_MODE_SW:
|
||||
reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
|
||||
break;
|
||||
case DWC3_OMAP_UTMI_MODE_HW:
|
||||
reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
|
||||
}
|
||||
|
||||
dwc3_omap_write_utmi_status(omap, reg);
|
||||
dwc3_omap_map_offset(omap);
|
||||
dwc3_omap_set_utmi_mode(omap);
|
||||
|
||||
/* check the DMA Status */
|
||||
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
|
||||
|
@ -515,31 +537,9 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
|||
|
||||
dwc3_omap_enable_irqs(omap);
|
||||
|
||||
if (of_property_read_bool(node, "extcon")) {
|
||||
edev = extcon_get_edev_by_phandle(dev, 0);
|
||||
if (IS_ERR(edev)) {
|
||||
dev_vdbg(dev, "couldn't get extcon device\n");
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
|
||||
ret = extcon_register_interest(&omap->extcon_vbus_dev,
|
||||
edev->name, "USB", &omap->vbus_nb);
|
||||
if (ret < 0)
|
||||
dev_vdbg(dev, "failed to register notifier for USB\n");
|
||||
omap->id_nb.notifier_call = dwc3_omap_id_notifier;
|
||||
ret = extcon_register_interest(&omap->extcon_id_dev, edev->name,
|
||||
"USB-HOST", &omap->id_nb);
|
||||
if (ret < 0)
|
||||
dev_vdbg(dev,
|
||||
"failed to register notifier for USB-HOST\n");
|
||||
|
||||
if (extcon_get_cable_state(edev, "USB") == true)
|
||||
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
|
||||
if (extcon_get_cable_state(edev, "USB-HOST") == true)
|
||||
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
|
||||
}
|
||||
ret = dwc3_omap_extcon_register(omap);
|
||||
if (ret < 0)
|
||||
goto err2;
|
||||
|
||||
ret = of_platform_populate(node, NULL, NULL, dev);
|
||||
if (ret) {
|
||||
|
|
|
@ -1971,8 +1971,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
|
|||
}
|
||||
|
||||
static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
|
||||
struct dwc3_ep *dep, const struct dwc3_event_depevt *event,
|
||||
int start_new)
|
||||
struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
|
||||
{
|
||||
unsigned status = 0;
|
||||
int clean_busy;
|
||||
|
@ -2039,7 +2038,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
|
|||
return;
|
||||
}
|
||||
|
||||
dwc3_endpoint_transfer_complete(dwc, dep, event, 1);
|
||||
dwc3_endpoint_transfer_complete(dwc, dep, event);
|
||||
break;
|
||||
case DWC3_DEPEVT_XFERINPROGRESS:
|
||||
if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
|
||||
|
@ -2048,7 +2047,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
|
|||
return;
|
||||
}
|
||||
|
||||
dwc3_endpoint_transfer_complete(dwc, dep, event, 0);
|
||||
dwc3_endpoint_transfer_complete(dwc, dep, event);
|
||||
break;
|
||||
case DWC3_DEPEVT_XFERNOTREADY:
|
||||
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
|
||||
|
|
|
@ -127,368 +127,7 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
|
|||
a module parameter as well.
|
||||
If unsure, say 2.
|
||||
|
||||
#
|
||||
# USB Peripheral Controller Support
|
||||
#
|
||||
# The order here is alphabetical, except that integrated controllers go
|
||||
# before discrete ones so they will be the initial/default value:
|
||||
# - integrated/SOC controllers first
|
||||
# - licensed IP used in both SOC and discrete versions
|
||||
# - discrete ones (including all PCI-only controllers)
|
||||
# - debug/dummy gadget+hcd is last.
|
||||
#
|
||||
menu "USB Peripheral Controller"
|
||||
|
||||
#
|
||||
# Integrated controllers
|
||||
#
|
||||
|
||||
config USB_AT91
|
||||
tristate "Atmel AT91 USB Device Port"
|
||||
depends on ARCH_AT91
|
||||
help
|
||||
Many Atmel AT91 processors (such as the AT91RM2000) have a
|
||||
full speed USB Device Port with support for five configurable
|
||||
endpoints (plus endpoint zero).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "at91_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_LPC32XX
|
||||
tristate "LPC32XX USB Peripheral Controller"
|
||||
depends on ARCH_LPC32XX && I2C
|
||||
select USB_ISP1301
|
||||
help
|
||||
This option selects the USB device controller in the LPC32xx SoC.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "lpc32xx_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_ATMEL_USBA
|
||||
tristate "Atmel USBA"
|
||||
depends on AVR32 || ARCH_AT91
|
||||
help
|
||||
USBA is the integrated high-speed USB Device controller on
|
||||
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
|
||||
|
||||
config USB_BCM63XX_UDC
|
||||
tristate "Broadcom BCM63xx Peripheral Controller"
|
||||
depends on BCM63XX
|
||||
help
|
||||
Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
|
||||
high speed USB Device Port with support for four fixed endpoints
|
||||
(plus endpoint zero).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "bcm63xx_udc".
|
||||
|
||||
config USB_FSL_USB2
|
||||
tristate "Freescale Highspeed USB DR Peripheral Controller"
|
||||
depends on FSL_SOC || ARCH_MXC
|
||||
select USB_FSL_MPH_DR_OF if OF
|
||||
help
|
||||
Some of Freescale PowerPC and i.MX processors have a High Speed
|
||||
Dual-Role(DR) USB controller, which supports device mode.
|
||||
|
||||
The number of programmable endpoints is different through
|
||||
SOC revisions.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "fsl_usb2_udc" and force
|
||||
all gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_FUSB300
|
||||
tristate "Faraday FUSB300 USB Peripheral Controller"
|
||||
depends on !PHYS_ADDR_T_64BIT && HAS_DMA
|
||||
help
|
||||
Faraday usb device controller FUSB300 driver
|
||||
|
||||
config USB_FOTG210_UDC
|
||||
depends on HAS_DMA
|
||||
tristate "Faraday FOTG210 USB Peripheral Controller"
|
||||
help
|
||||
Faraday USB2.0 OTG controller which can be configured as
|
||||
high speed or full speed USB device. This driver supppors
|
||||
Bulk Transfer so far.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "fotg210_udc".
|
||||
|
||||
config USB_GR_UDC
|
||||
tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
|
||||
VHDL IP core library.
|
||||
|
||||
config USB_OMAP
|
||||
tristate "OMAP USB Device Controller"
|
||||
depends on ARCH_OMAP1
|
||||
depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
|
||||
help
|
||||
Many Texas Instruments OMAP processors have flexible full
|
||||
speed USB device controllers, with support for up to 30
|
||||
endpoints (plus endpoint zero). This driver supports the
|
||||
controller in the OMAP 1611, and should work with controllers
|
||||
in other OMAP processors too, given minor tweaks.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "omap_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_PXA25X
|
||||
tristate "PXA 25x or IXP 4xx"
|
||||
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
|
||||
help
|
||||
Intel's PXA 25x series XScale ARM-5TE processors include
|
||||
an integrated full speed USB 1.1 device controller. The
|
||||
controller in the IXP 4xx series is register-compatible.
|
||||
|
||||
It has fifteen fixed-function endpoints, as well as endpoint
|
||||
zero (for control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "pxa25x_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
# 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_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_R8A66597
|
||||
tristate "Renesas R8A66597 USB Peripheral Controller"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
R8A66597 is a discrete USB host and peripheral controller chip that
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
It has nine configurable endpoints, and endpoint zero.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "r8a66597_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_RENESAS_USBHS_UDC
|
||||
tristate 'Renesas USBHS controller'
|
||||
depends on USB_RENESAS_USBHS
|
||||
help
|
||||
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 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_PXA27X
|
||||
tristate "PXA 27x"
|
||||
help
|
||||
Intel's PXA 27x series XScale ARM v5TE processors include
|
||||
an integrated full speed USB 1.1 device controller.
|
||||
|
||||
It has up to 23 endpoints, as well as endpoint zero (for
|
||||
control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "pxa27x_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_S3C2410
|
||||
tristate "S3C2410 USB Device Controller"
|
||||
depends on ARCH_S3C24XX
|
||||
help
|
||||
Samsung's S3C2410 is an ARM-4 processor with an integrated
|
||||
full speed USB 1.1 device controller. It has 4 configurable
|
||||
endpoints, as well as endpoint zero (for control transfers).
|
||||
|
||||
This driver has been tested on the S3C2410, S3C2412, and
|
||||
S3C2440 processors.
|
||||
|
||||
config USB_S3C2410_DEBUG
|
||||
boolean "S3C2410 udc debug messages"
|
||||
depends on USB_S3C2410
|
||||
|
||||
config USB_S3C_HSUDC
|
||||
tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
|
||||
depends on ARCH_S3C24XX
|
||||
help
|
||||
Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
|
||||
integrated with dual speed USB 2.0 device controller. It has
|
||||
8 endpoints, as well as endpoint zero.
|
||||
|
||||
This driver has been tested on S3C2416 and S3C2450 processors.
|
||||
|
||||
config USB_MV_UDC
|
||||
tristate "Marvell USB2.0 Device Controller"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
Marvell Socs (including PXA and MMP series) include a high speed
|
||||
USB2.0 OTG controller, which can be configured as high speed or
|
||||
full speed USB peripheral.
|
||||
|
||||
config USB_MV_U3D
|
||||
depends on HAS_DMA
|
||||
tristate "MARVELL PXA2128 USB 3.0 controller"
|
||||
help
|
||||
MARVELL PXA2128 Processor series include a super speed USB3.0 device
|
||||
controller, which support super speed USB peripheral.
|
||||
|
||||
#
|
||||
# Controllers available in both integrated and discrete versions
|
||||
#
|
||||
|
||||
config USB_M66592
|
||||
tristate "Renesas M66592 USB Peripheral Controller"
|
||||
help
|
||||
M66592 is a discrete USB peripheral controller chip that
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
It has seven configurable endpoints, and endpoint zero.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "m66592_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
#
|
||||
# Controllers available only in discrete form (and all PCI controllers)
|
||||
#
|
||||
|
||||
config USB_AMD5536UDC
|
||||
tristate "AMD5536 UDC"
|
||||
depends on PCI
|
||||
help
|
||||
The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
|
||||
It is a USB Highspeed DMA capable USB device controller. Beside ep0
|
||||
it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
|
||||
The UDC port supports OTG operation, and may be used as a host port
|
||||
if it's not being used to implement peripheral or OTG roles.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "amd5536udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
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
|
||||
QE/CPM2 USB controller, which support device mode with 4
|
||||
programmable endpoints. This driver supports the
|
||||
controller in the MPC8360 and MPC8272, and should work with
|
||||
controllers having QE or CPM2, given minor tweaks.
|
||||
|
||||
Set CONFIG_USB_GADGET to "m" to build this driver as a
|
||||
dynamically linked module called "fsl_qe_udc".
|
||||
|
||||
config USB_NET2272
|
||||
tristate "PLX NET2272"
|
||||
help
|
||||
PLX NET2272 is a USB peripheral controller which supports
|
||||
both full and high speed USB 2.0 data transfers.
|
||||
|
||||
It has three configurable endpoints, as well as endpoint zero
|
||||
(for control transfer).
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "net2272" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_NET2272_DMA
|
||||
boolean "Support external DMA controller"
|
||||
depends on USB_NET2272 && HAS_DMA
|
||||
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
|
||||
help
|
||||
NetChip 2280 / 2282 is a PCI based USB peripheral controller which
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
|
||||
It has six configurable endpoints, as well as endpoint zero
|
||||
(for control transfers) and several endpoints with dedicated
|
||||
functions.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "net2280" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_GOKU
|
||||
tristate "Toshiba TC86C001 'Goku-S'"
|
||||
depends on PCI
|
||||
help
|
||||
The Toshiba TC86C001 is a PCI device which includes controllers
|
||||
for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
|
||||
|
||||
The device controller has three configurable (bulk or interrupt)
|
||||
endpoints, plus endpoint zero (for control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "goku_udc" and to force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_EG20T
|
||||
tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
|
||||
depends on PCI
|
||||
help
|
||||
This is a USB device driver for EG20T PCH.
|
||||
EG20T PCH is the platform controller hub that is used in Intel's
|
||||
general embedded platform. EG20T PCH has USB device interface.
|
||||
Using this interface, it is able to access system devices connected
|
||||
to USB device.
|
||||
This driver enables USB device function.
|
||||
USB device is a USB peripheral controller which
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
This driver supports both control transfer and bulk transfer modes.
|
||||
This driver dose not support interrupt transfer or isochronous
|
||||
transfer modes.
|
||||
|
||||
This driver also can be used for LAPIS Semiconductor's ML7213 which is
|
||||
for IVI(In-Vehicle Infotainment) use.
|
||||
ML7831 is for general purpose use.
|
||||
ML7213/ML7831 is companion chip for Intel Atom E6xx series.
|
||||
ML7213/ML7831 is completely compatible for Intel EG20T PCH.
|
||||
|
||||
#
|
||||
# LAST -- dummy/emulated controller
|
||||
#
|
||||
|
||||
config USB_DUMMY_HCD
|
||||
tristate "Dummy HCD (DEVELOPMENT)"
|
||||
depends on USB=y || (USB=m && USB_GADGET=m)
|
||||
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.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "dummy_hcd" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears
|
||||
# first and will be selected by default.
|
||||
|
||||
endmenu
|
||||
source "drivers/usb/gadget/udc/Kconfig"
|
||||
|
||||
#
|
||||
# USB Gadget Drivers
|
||||
|
@ -714,466 +353,7 @@ config USB_CONFIGFS_F_FS
|
|||
implemented in kernel space (for instance Ethernet, serial or
|
||||
mass storage) and other are implemented in user space.
|
||||
|
||||
config USB_ZERO
|
||||
tristate "Gadget Zero (DEVELOPMENT)"
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_SS_LB
|
||||
help
|
||||
Gadget Zero is a two-configuration device. It either sinks and
|
||||
sources bulk data; or it loops back a configurable number of
|
||||
transfers. It also implements control requests, for "chapter 9"
|
||||
conformance. The driver needs only two bulk-capable endpoints, so
|
||||
it can work on top of most device-side usb controllers. It's
|
||||
useful for testing, and is also a working example showing how
|
||||
USB "gadget drivers" can be written.
|
||||
|
||||
Make this be the first driver you try using on top of any new
|
||||
USB peripheral controller driver. Then you can use host-side
|
||||
test software, like the "usbtest" driver, to put your hardware
|
||||
and its driver through a basic set of functional tests.
|
||||
|
||||
Gadget Zero also works with the host-side "usb-skeleton" driver,
|
||||
and with many kinds of host-side test software. You may need
|
||||
to tweak product and vendor IDs before host software knows about
|
||||
this device, and arrange to select an appropriate configuration.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_zero".
|
||||
|
||||
config USB_ZERO_HNPTEST
|
||||
boolean "HNP Test Device"
|
||||
depends on USB_ZERO && USB_OTG
|
||||
help
|
||||
You can configure this device to enumerate using the device
|
||||
identifiers of the USB-OTG test device. That means that when
|
||||
this gadget connects to another OTG device, with this one using
|
||||
the "B-Peripheral" role, that device will use HNP to let this
|
||||
one serve as the USB host instead (in the "B-Host" role).
|
||||
|
||||
config USB_AUDIO
|
||||
tristate "Audio Gadget"
|
||||
depends on SND
|
||||
select USB_LIBCOMPOSITE
|
||||
select SND_PCM
|
||||
help
|
||||
This Gadget Audio driver is compatible with USB Audio Class
|
||||
specification 2.0. It implements 1 AudioControl interface,
|
||||
1 AudioStreaming Interface each for USB-OUT and USB-IN.
|
||||
Number of channels, sample rate and sample size can be
|
||||
specified as module parameters.
|
||||
This driver doesn't expect any real Audio codec to be present
|
||||
on the device - the audio streams are simply sinked to and
|
||||
sourced from a virtual ALSA sound card created. The user-space
|
||||
application may choose to do whatever it wants with the data
|
||||
received from the USB Host and choose to provide whatever it
|
||||
wants as audio data to the USB Host.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_audio".
|
||||
|
||||
config GADGET_UAC1
|
||||
bool "UAC 1.0 (Legacy)"
|
||||
depends on USB_AUDIO
|
||||
help
|
||||
If you instead want older UAC Spec-1.0 driver that also has audio
|
||||
paths hardwired to the Audio codec chip on-board and doesn't work
|
||||
without one.
|
||||
|
||||
config USB_ETH
|
||||
tristate "Ethernet Gadget (with CDC Ethernet support)"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_ETHER
|
||||
select USB_F_ECM
|
||||
select USB_F_SUBSET
|
||||
select CRC32
|
||||
help
|
||||
This driver implements Ethernet style communication, in one of
|
||||
several ways:
|
||||
|
||||
- The "Communication Device Class" (CDC) Ethernet Control Model.
|
||||
That protocol is often avoided with pure Ethernet adapters, in
|
||||
favor of simpler vendor-specific hardware, but is widely
|
||||
supported by firmware for smart network devices.
|
||||
|
||||
- On hardware can't implement that protocol, a simple CDC subset
|
||||
is used, placing fewer demands on USB.
|
||||
|
||||
- CDC Ethernet Emulation Model (EEM) is a newer standard that has
|
||||
a simpler interface that can be used by more USB hardware.
|
||||
|
||||
RNDIS support is an additional option, more demanding than than
|
||||
subset.
|
||||
|
||||
Within the USB device, this gadget driver exposes a network device
|
||||
"usbX", where X depends on what other networking devices you have.
|
||||
Treat it like a two-node Ethernet link: host, and gadget.
|
||||
|
||||
The Linux-USB host-side "usbnet" driver interoperates with this
|
||||
driver, so that deep I/O queues can be supported. On 2.4 kernels,
|
||||
use "CDCEther" instead, if you're using the CDC option. That CDC
|
||||
mode should also interoperate with standard CDC Ethernet class
|
||||
drivers on other host operating systems.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_ether".
|
||||
|
||||
config USB_ETH_RNDIS
|
||||
bool "RNDIS support"
|
||||
depends on USB_ETH
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_RNDIS
|
||||
default y
|
||||
help
|
||||
Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
|
||||
and Microsoft provides redistributable binary RNDIS drivers for
|
||||
older versions of Windows.
|
||||
|
||||
If you say "y" here, the Ethernet gadget driver will try to provide
|
||||
a second device configuration, supporting RNDIS to talk to such
|
||||
Microsoft USB hosts.
|
||||
|
||||
To make MS-Windows work with this, use Documentation/usb/linux.inf
|
||||
as the "driver info file". For versions of MS-Windows older than
|
||||
XP, you'll need to download drivers from Microsoft's website; a URL
|
||||
is given in comments found in that info file.
|
||||
|
||||
config USB_ETH_EEM
|
||||
bool "Ethernet Emulation Model (EEM) support"
|
||||
depends on USB_ETH
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_EEM
|
||||
default n
|
||||
help
|
||||
CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
|
||||
and therefore can be supported by more hardware. Technically ECM and
|
||||
EEM are designed for different applications. The ECM model extends
|
||||
the network interface to the target (e.g. a USB cable modem), and the
|
||||
EEM model is for mobile devices to communicate with hosts using
|
||||
ethernet over USB. For Linux gadgets, however, the interface with
|
||||
the host is the same (a usbX device), so the differences are minimal.
|
||||
|
||||
If you say "y" here, the Ethernet gadget driver will use the EEM
|
||||
protocol rather than ECM. If unsure, say "n".
|
||||
|
||||
config USB_G_NCM
|
||||
tristate "Network Control Model (NCM) support"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_ETHER
|
||||
select USB_F_NCM
|
||||
select CRC32
|
||||
help
|
||||
This driver implements USB CDC NCM subclass standard. NCM is
|
||||
an advanced protocol for Ethernet encapsulation, allows grouping
|
||||
of several ethernet frames into one USB transfer and different
|
||||
alignment possibilities.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_ncm".
|
||||
|
||||
config USB_GADGETFS
|
||||
tristate "Gadget Filesystem"
|
||||
help
|
||||
This driver provides a filesystem based API that lets user mode
|
||||
programs implement a single-configuration USB device, including
|
||||
endpoint I/O and control requests that don't relate to enumeration.
|
||||
All endpoints, transfer speeds, and transfer types supported by
|
||||
the hardware are available, through read() and write() calls.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "gadgetfs".
|
||||
|
||||
config USB_FUNCTIONFS
|
||||
tristate "Function Filesystem"
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_FS
|
||||
select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
|
||||
help
|
||||
The Function Filesystem (FunctionFS) lets one create USB
|
||||
composite functions in user space in the same way GadgetFS
|
||||
lets one create USB gadgets in user space. This allows creation
|
||||
of composite gadgets such that some of the functions are
|
||||
implemented in kernel space (for instance Ethernet, serial or
|
||||
mass storage) and other are implemented in user space.
|
||||
|
||||
If you say "y" or "m" here you will be able what kind of
|
||||
configurations the gadget will provide.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build
|
||||
a dynamically linked module called "g_ffs".
|
||||
|
||||
config USB_FUNCTIONFS_ETH
|
||||
bool "Include configuration with CDC ECM (Ethernet)"
|
||||
depends on USB_FUNCTIONFS && NET
|
||||
select USB_U_ETHER
|
||||
select USB_F_ECM
|
||||
select USB_F_SUBSET
|
||||
help
|
||||
Include a configuration with CDC ECM function (Ethernet) and the
|
||||
Function Filesystem.
|
||||
|
||||
config USB_FUNCTIONFS_RNDIS
|
||||
bool "Include configuration with RNDIS (Ethernet)"
|
||||
depends on USB_FUNCTIONFS && NET
|
||||
select USB_U_ETHER
|
||||
select USB_F_RNDIS
|
||||
help
|
||||
Include a configuration with RNDIS function (Ethernet) and the Filesystem.
|
||||
|
||||
config USB_FUNCTIONFS_GENERIC
|
||||
bool "Include 'pure' configuration"
|
||||
depends on USB_FUNCTIONFS
|
||||
help
|
||||
Include a configuration with the Function Filesystem alone with
|
||||
no Ethernet interface.
|
||||
|
||||
config USB_MASS_STORAGE
|
||||
tristate "Mass Storage Gadget"
|
||||
depends on BLOCK
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_MASS_STORAGE
|
||||
help
|
||||
The Mass Storage Gadget acts as a USB Mass Storage disk drive.
|
||||
As its storage repository it can use a regular file or a block
|
||||
device (in much the same way as the "loop" device driver),
|
||||
specified as a module parameter or sysfs option.
|
||||
|
||||
This driver is a replacement for now removed File-backed
|
||||
Storage Gadget (g_file_storage).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build
|
||||
a dynamically linked module called "g_mass_storage".
|
||||
|
||||
config USB_GADGET_TARGET
|
||||
tristate "USB Gadget Target Fabric Module"
|
||||
depends on TARGET_CORE
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
This fabric is an USB gadget. Two USB protocols are supported that is
|
||||
BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
|
||||
advertised on alternative interface 0 (primary) and UAS is on
|
||||
alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
|
||||
UAS utilizes the USB 3.0 feature called streams support.
|
||||
|
||||
config USB_G_SERIAL
|
||||
tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
|
||||
depends on TTY
|
||||
select USB_U_SERIAL
|
||||
select USB_F_ACM
|
||||
select USB_F_SERIAL
|
||||
select USB_F_OBEX
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Serial Gadget talks to the Linux-USB generic serial driver.
|
||||
This driver supports a CDC-ACM module option, which can be used
|
||||
to interoperate with MS-Windows hosts or with the Linux-USB
|
||||
"cdc-acm" driver.
|
||||
|
||||
This driver also supports a CDC-OBEX option. You will need a
|
||||
user space OBEX server talking to /dev/ttyGS*, since the kernel
|
||||
itself doesn't implement the OBEX protocol.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_serial".
|
||||
|
||||
For more information, see Documentation/usb/gadget_serial.txt
|
||||
which includes instructions and a "driver info file" needed to
|
||||
make MS-Windows work with CDC ACM.
|
||||
|
||||
config USB_MIDI_GADGET
|
||||
tristate "MIDI Gadget"
|
||||
depends on SND
|
||||
select USB_LIBCOMPOSITE
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
The MIDI Gadget acts as a USB Audio device, with one MIDI
|
||||
input and one MIDI output. These MIDI jacks appear as
|
||||
a sound "card" in the ALSA sound system. Other MIDI
|
||||
connections can then be made on the gadget system, using
|
||||
ALSA's aconnect utility etc.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_midi".
|
||||
|
||||
config USB_G_PRINTER
|
||||
tristate "Printer Gadget"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Printer Gadget channels data between the USB host and a
|
||||
userspace program driving the print engine. The user space
|
||||
program reads and writes the device file /dev/g_printer to
|
||||
receive or send printer data. It can use ioctl calls to
|
||||
the device file to get or set printer status.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_printer".
|
||||
|
||||
For more information, see Documentation/usb/gadget_printer.txt
|
||||
which includes sample code for accessing the device file.
|
||||
|
||||
if TTY
|
||||
|
||||
config USB_CDC_COMPOSITE
|
||||
tristate "CDC Composite Device (Ethernet and ACM)"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_SERIAL
|
||||
select USB_U_ETHER
|
||||
select USB_F_ACM
|
||||
select USB_F_ECM
|
||||
help
|
||||
This driver provides two functions in one configuration:
|
||||
a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
|
||||
|
||||
This driver requires four bulk and two interrupt endpoints,
|
||||
plus the ability to handle altsettings. Not all peripheral
|
||||
controllers are that capable.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module.
|
||||
|
||||
config USB_G_NOKIA
|
||||
tristate "Nokia composite gadget"
|
||||
depends on PHONET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_SERIAL
|
||||
select USB_U_ETHER
|
||||
select USB_F_ACM
|
||||
select USB_F_OBEX
|
||||
select USB_F_PHONET
|
||||
select USB_F_ECM
|
||||
help
|
||||
The Nokia composite gadget provides support for acm, obex
|
||||
and phonet in only one composite gadget driver.
|
||||
|
||||
It's only really useful for N900 hardware. If you're building
|
||||
a kernel for N900, say Y or M here. If unsure, say N.
|
||||
|
||||
config USB_G_ACM_MS
|
||||
tristate "CDC Composite Device (ACM and mass storage)"
|
||||
depends on BLOCK
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_SERIAL
|
||||
select USB_F_ACM
|
||||
select USB_F_MASS_STORAGE
|
||||
help
|
||||
This driver provides two functions in one configuration:
|
||||
a mass storage, and a CDC ACM (serial port) link.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_acm_ms".
|
||||
|
||||
config USB_G_MULTI
|
||||
tristate "Multifunction Composite Gadget"
|
||||
depends on BLOCK && NET
|
||||
select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_SERIAL
|
||||
select USB_U_ETHER
|
||||
select USB_F_ACM
|
||||
select USB_F_MASS_STORAGE
|
||||
help
|
||||
The Multifunction Composite Gadget provides Ethernet (RNDIS
|
||||
and/or CDC Ethernet), mass storage and ACM serial link
|
||||
interfaces.
|
||||
|
||||
You will be asked to choose which of the two configurations is
|
||||
to be available in the gadget. At least one configuration must
|
||||
be chosen to make the gadget usable. Selecting more than one
|
||||
configuration will prevent Windows from automatically detecting
|
||||
the gadget as a composite gadget, so an INF file will be needed to
|
||||
use the gadget.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_multi".
|
||||
|
||||
config USB_G_MULTI_RNDIS
|
||||
bool "RNDIS + CDC Serial + Storage configuration"
|
||||
depends on USB_G_MULTI
|
||||
select USB_F_RNDIS
|
||||
default y
|
||||
help
|
||||
This option enables a configuration with RNDIS, CDC Serial and
|
||||
Mass Storage functions available in the Multifunction Composite
|
||||
Gadget. This is the configuration dedicated for Windows since RNDIS
|
||||
is Microsoft's protocol.
|
||||
|
||||
If unsure, say "y".
|
||||
|
||||
config USB_G_MULTI_CDC
|
||||
bool "CDC Ethernet + CDC Serial + Storage configuration"
|
||||
depends on USB_G_MULTI
|
||||
default n
|
||||
select USB_F_ECM
|
||||
help
|
||||
This option enables a configuration with CDC Ethernet (ECM), CDC
|
||||
Serial and Mass Storage functions available in the Multifunction
|
||||
Composite Gadget.
|
||||
|
||||
If unsure, say "y".
|
||||
|
||||
endif # TTY
|
||||
|
||||
config USB_G_HID
|
||||
tristate "HID Gadget"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The HID gadget driver provides generic emulation of USB
|
||||
Human Interface Devices (HID).
|
||||
|
||||
For more information, see Documentation/usb/gadget_hid.txt which
|
||||
includes sample code for accessing the device files.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_hid".
|
||||
|
||||
# Standalone / single function gadgets
|
||||
config USB_G_DBGP
|
||||
tristate "EHCI Debug Device Gadget"
|
||||
depends on TTY
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
This gadget emulates an EHCI Debug device. This is useful when you want
|
||||
to interact with an EHCI Debug Port.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_dbgp".
|
||||
|
||||
if USB_G_DBGP
|
||||
choice
|
||||
prompt "EHCI Debug Device mode"
|
||||
default USB_G_DBGP_SERIAL
|
||||
|
||||
config USB_G_DBGP_PRINTK
|
||||
depends on USB_G_DBGP
|
||||
bool "printk"
|
||||
help
|
||||
Directly printk() received data. No interaction.
|
||||
|
||||
config USB_G_DBGP_SERIAL
|
||||
depends on USB_G_DBGP
|
||||
select USB_U_SERIAL
|
||||
bool "serial"
|
||||
help
|
||||
Userland can interact using /dev/ttyGSxxx.
|
||||
endchoice
|
||||
endif
|
||||
|
||||
# put drivers that need isochronous transfer support (for audio
|
||||
# or video class gadget drivers), or specific hardware, here.
|
||||
config USB_G_WEBCAM
|
||||
tristate "USB Webcam Gadget"
|
||||
depends on VIDEO_DEV
|
||||
select USB_LIBCOMPOSITE
|
||||
select VIDEOBUF2_VMALLOC
|
||||
help
|
||||
The Webcam Gadget acts as a composite USB Audio and Video Class
|
||||
device. It provides a userspace API to process UVC control requests
|
||||
and stream video data to the host.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_webcam".
|
||||
source "drivers/usb/gadget/legacy/Kconfig"
|
||||
|
||||
endchoice
|
||||
|
||||
|
|
|
@ -1,105 +1,12 @@
|
|||
#
|
||||
# USB peripheral controller drivers
|
||||
#
|
||||
ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
|
||||
ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG
|
||||
subdir-ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
|
||||
subdir-ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG
|
||||
ccflags-y += -I$(PWD)/drivers/usb/gadget/udc
|
||||
|
||||
obj-$(CONFIG_USB_GADGET) += udc-core.o
|
||||
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
|
||||
libcomposite-y := usbstring.o config.o epautoconf.o
|
||||
libcomposite-y += composite.o functions.o configfs.o u_f.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
|
||||
obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
|
||||
obj-$(CONFIG_USB_GOKU) += goku_udc.o
|
||||
obj-$(CONFIG_USB_OMAP) += omap_udc.o
|
||||
obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
|
||||
obj-$(CONFIG_USB_AT91) += at91_udc.o
|
||||
obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
|
||||
obj-$(CONFIG_USB_BCM63XX_UDC) += bcm63xx_udc.o
|
||||
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
|
||||
fsl_usb2_udc-y := fsl_udc_core.o
|
||||
fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
|
||||
obj-$(CONFIG_USB_M66592) += m66592-udc.o
|
||||
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
|
||||
obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
|
||||
obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o
|
||||
obj-$(CONFIG_USB_LPC32XX) += lpc32xx_udc.o
|
||||
obj-$(CONFIG_USB_EG20T) += pch_udc.o
|
||||
obj-$(CONFIG_USB_MV_UDC) += mv_udc.o
|
||||
mv_udc-y := mv_udc_core.o
|
||||
obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
|
||||
obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o
|
||||
obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
|
||||
obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
|
||||
|
||||
# USB Functions
|
||||
usb_f_acm-y := f_acm.o
|
||||
obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o
|
||||
usb_f_ss_lb-y := f_loopback.o f_sourcesink.o
|
||||
obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o
|
||||
obj-$(CONFIG_USB_U_SERIAL) += u_serial.o
|
||||
usb_f_serial-y := f_serial.o
|
||||
obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o
|
||||
usb_f_obex-y := f_obex.o
|
||||
obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o
|
||||
obj-$(CONFIG_USB_U_ETHER) += u_ether.o
|
||||
usb_f_ncm-y := f_ncm.o
|
||||
obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o
|
||||
usb_f_ecm-y := f_ecm.o
|
||||
obj-$(CONFIG_USB_F_ECM) += usb_f_ecm.o
|
||||
usb_f_phonet-y := f_phonet.o
|
||||
obj-$(CONFIG_USB_F_PHONET) += usb_f_phonet.o
|
||||
usb_f_eem-y := f_eem.o
|
||||
obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o
|
||||
usb_f_ecm_subset-y := f_subset.o
|
||||
obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o
|
||||
usb_f_rndis-y := f_rndis.o rndis.o
|
||||
obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o
|
||||
usb_f_mass_storage-y := f_mass_storage.o storage_common.o
|
||||
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
|
||||
usb_f_fs-y := f_fs.o
|
||||
obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
|
||||
|
||||
#
|
||||
# USB gadget drivers
|
||||
#
|
||||
g_zero-y := zero.o
|
||||
g_audio-y := audio.o
|
||||
g_ether-y := ether.o
|
||||
g_serial-y := serial.o
|
||||
g_midi-y := gmidi.o
|
||||
gadgetfs-y := inode.o
|
||||
g_mass_storage-y := mass_storage.o
|
||||
g_printer-y := printer.o
|
||||
g_cdc-y := cdc2.o
|
||||
g_multi-y := multi.o
|
||||
g_hid-y := hid.o
|
||||
g_dbgp-y := dbgp.o
|
||||
g_nokia-y := nokia.o
|
||||
g_webcam-y := webcam.o
|
||||
g_ncm-y := ncm.o
|
||||
g_acm_ms-y := acm_ms.o
|
||||
g_tcm_usb_gadget-y := tcm_usb_gadget.o
|
||||
|
||||
obj-$(CONFIG_USB_ZERO) += g_zero.o
|
||||
obj-$(CONFIG_USB_AUDIO) += g_audio.o
|
||||
obj-$(CONFIG_USB_ETH) += g_ether.o
|
||||
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
|
||||
obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
|
||||
obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
|
||||
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
|
||||
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
|
||||
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
|
||||
obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
|
||||
obj-$(CONFIG_USB_G_HID) += g_hid.o
|
||||
obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o
|
||||
obj-$(CONFIG_USB_G_MULTI) += g_multi.o
|
||||
obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
|
||||
obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
|
||||
obj-$(CONFIG_USB_G_NCM) += g_ncm.o
|
||||
obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
|
||||
obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
|
||||
obj-$(CONFIG_USB_GADGET) += udc/ function/ legacy/
|
||||
|
|
|
@ -1956,6 +1956,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
|
|||
}
|
||||
if (cdev->req) {
|
||||
kfree(cdev->req->buf);
|
||||
usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
|
||||
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
|
||||
}
|
||||
cdev->next_string_id = 0;
|
||||
|
|
|
@ -1021,12 +1021,10 @@ static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
|
|||
|
||||
if (page[len - 1] == '\n' || page[len - 1] == '\0')
|
||||
--len;
|
||||
new_data = kzalloc(len, GFP_KERNEL);
|
||||
new_data = kmemdup(page, len, GFP_KERNEL);
|
||||
if (!new_data)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(new_data, page, len);
|
||||
|
||||
if (desc->opts_mutex)
|
||||
mutex_lock(desc->opts_mutex);
|
||||
kfree(ext_prop->data);
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# USB peripheral controller drivers
|
||||
#
|
||||
|
||||
ccflags-y := -I$(PWD)/drivers/usb/gadget/
|
||||
ccflags-y += -I$(PWD)/drivers/usb/gadget/udc/
|
||||
|
||||
# USB Functions
|
||||
usb_f_acm-y := f_acm.o
|
||||
obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o
|
||||
usb_f_ss_lb-y := f_loopback.o f_sourcesink.o
|
||||
obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o
|
||||
obj-$(CONFIG_USB_U_SERIAL) += u_serial.o
|
||||
usb_f_serial-y := f_serial.o
|
||||
obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o
|
||||
usb_f_obex-y := f_obex.o
|
||||
obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o
|
||||
obj-$(CONFIG_USB_U_ETHER) += u_ether.o
|
||||
usb_f_ncm-y := f_ncm.o
|
||||
obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o
|
||||
usb_f_ecm-y := f_ecm.o
|
||||
obj-$(CONFIG_USB_F_ECM) += usb_f_ecm.o
|
||||
usb_f_phonet-y := f_phonet.o
|
||||
obj-$(CONFIG_USB_F_PHONET) += usb_f_phonet.o
|
||||
usb_f_eem-y := f_eem.o
|
||||
obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o
|
||||
usb_f_ecm_subset-y := f_subset.o
|
||||
obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o
|
||||
usb_f_rndis-y := f_rndis.o rndis.o
|
||||
obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o
|
||||
usb_f_mass_storage-y := f_mass_storage.o storage_common.o
|
||||
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
|
||||
usb_f_fs-y := f_fs.o
|
||||
obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
|
|
@ -355,20 +355,18 @@ static struct sk_buff *eem_wrap(struct gether *port, struct sk_buff *skb)
|
|||
int padlen = 0;
|
||||
u16 len = skb->len;
|
||||
|
||||
if (!skb_cloned(skb)) {
|
||||
int headroom = skb_headroom(skb);
|
||||
int tailroom = skb_tailroom(skb);
|
||||
int headroom = skb_headroom(skb);
|
||||
int tailroom = skb_tailroom(skb);
|
||||
|
||||
/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
|
||||
* stick two bytes of zero-length EEM packet on the end.
|
||||
*/
|
||||
if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
|
||||
padlen += 2;
|
||||
/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
|
||||
* stick two bytes of zero-length EEM packet on the end.
|
||||
*/
|
||||
if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
|
||||
padlen += 2;
|
||||
|
||||
if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
|
||||
(headroom >= EEM_HLEN))
|
||||
goto done;
|
||||
}
|
||||
if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
|
||||
(headroom >= EEM_HLEN) && !skb_cloned(skb))
|
||||
goto done;
|
||||
|
||||
skb2 = skb_copy_expand(skb, EEM_HLEN, ETH_FCS_LEN + padlen, GFP_ATOMIC);
|
||||
dev_kfree_skb_any(skb);
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "u_fs.h"
|
||||
#include "u_f.h"
|
||||
#include "u_os_desc.h"
|
||||
#include "configfs.h"
|
||||
|
||||
#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
|
||||
|
@ -1646,13 +1647,22 @@ enum ffs_entity_type {
|
|||
FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT
|
||||
};
|
||||
|
||||
enum ffs_os_desc_type {
|
||||
FFS_OS_DESC, FFS_OS_DESC_EXT_COMPAT, FFS_OS_DESC_EXT_PROP
|
||||
};
|
||||
|
||||
typedef int (*ffs_entity_callback)(enum ffs_entity_type entity,
|
||||
u8 *valuep,
|
||||
struct usb_descriptor_header *desc,
|
||||
void *priv);
|
||||
|
||||
static int __must_check ffs_do_desc(char *data, unsigned len,
|
||||
ffs_entity_callback entity, void *priv)
|
||||
typedef int (*ffs_os_desc_callback)(enum ffs_os_desc_type entity,
|
||||
struct usb_os_desc_header *h, void *data,
|
||||
unsigned len, void *priv);
|
||||
|
||||
static int __must_check ffs_do_single_desc(char *data, unsigned len,
|
||||
ffs_entity_callback entity,
|
||||
void *priv)
|
||||
{
|
||||
struct usb_descriptor_header *_ds = (void *)data;
|
||||
u8 length;
|
||||
|
@ -1804,7 +1814,7 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
|
|||
if (!data)
|
||||
return _len - len;
|
||||
|
||||
ret = ffs_do_desc(data, len, entity, priv);
|
||||
ret = ffs_do_single_desc(data, len, entity, priv);
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_debug("%s returns %d\n", __func__, ret);
|
||||
return ret;
|
||||
|
@ -1857,11 +1867,191 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __ffs_do_os_desc_header(enum ffs_os_desc_type *next_type,
|
||||
struct usb_os_desc_header *desc)
|
||||
{
|
||||
u16 bcd_version = le16_to_cpu(desc->bcdVersion);
|
||||
u16 w_index = le16_to_cpu(desc->wIndex);
|
||||
|
||||
if (bcd_version != 1) {
|
||||
pr_vdebug("unsupported os descriptors version: %d",
|
||||
bcd_version);
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (w_index) {
|
||||
case 0x4:
|
||||
*next_type = FFS_OS_DESC_EXT_COMPAT;
|
||||
break;
|
||||
case 0x5:
|
||||
*next_type = FFS_OS_DESC_EXT_PROP;
|
||||
break;
|
||||
default:
|
||||
pr_vdebug("unsupported os descriptor type: %d", w_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return sizeof(*desc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process all extended compatibility/extended property descriptors
|
||||
* of a feature descriptor
|
||||
*/
|
||||
static int __must_check ffs_do_single_os_desc(char *data, unsigned len,
|
||||
enum ffs_os_desc_type type,
|
||||
u16 feature_count,
|
||||
ffs_os_desc_callback entity,
|
||||
void *priv,
|
||||
struct usb_os_desc_header *h)
|
||||
{
|
||||
int ret;
|
||||
const unsigned _len = len;
|
||||
|
||||
ENTER();
|
||||
|
||||
/* loop over all ext compat/ext prop descriptors */
|
||||
while (feature_count--) {
|
||||
ret = entity(type, h, data, len, priv);
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_debug("bad OS descriptor, type: %d\n", type);
|
||||
return ret;
|
||||
}
|
||||
data += ret;
|
||||
len -= ret;
|
||||
}
|
||||
return _len - len;
|
||||
}
|
||||
|
||||
/* Process a number of complete Feature Descriptors (Ext Compat or Ext Prop) */
|
||||
static int __must_check ffs_do_os_descs(unsigned count,
|
||||
char *data, unsigned len,
|
||||
ffs_os_desc_callback entity, void *priv)
|
||||
{
|
||||
const unsigned _len = len;
|
||||
unsigned long num = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
for (num = 0; num < count; ++num) {
|
||||
int ret;
|
||||
enum ffs_os_desc_type type;
|
||||
u16 feature_count;
|
||||
struct usb_os_desc_header *desc = (void *)data;
|
||||
|
||||
if (len < sizeof(*desc))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Record "descriptor" entity.
|
||||
* Process dwLength, bcdVersion, wIndex, get b/wCount.
|
||||
* Move the data pointer to the beginning of extended
|
||||
* compatibilities proper or extended properties proper
|
||||
* portions of the data
|
||||
*/
|
||||
if (le32_to_cpu(desc->dwLength) > len)
|
||||
return -EINVAL;
|
||||
|
||||
ret = __ffs_do_os_desc_header(&type, desc);
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_debug("entity OS_DESCRIPTOR(%02lx); ret = %d\n",
|
||||
num, ret);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* 16-bit hex "?? 00" Little Endian looks like 8-bit hex "??"
|
||||
*/
|
||||
feature_count = le16_to_cpu(desc->wCount);
|
||||
if (type == FFS_OS_DESC_EXT_COMPAT &&
|
||||
(feature_count > 255 || desc->Reserved))
|
||||
return -EINVAL;
|
||||
len -= ret;
|
||||
data += ret;
|
||||
|
||||
/*
|
||||
* Process all function/property descriptors
|
||||
* of this Feature Descriptor
|
||||
*/
|
||||
ret = ffs_do_single_os_desc(data, len, type,
|
||||
feature_count, entity, priv, desc);
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_debug("%s returns %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
len -= ret;
|
||||
data += ret;
|
||||
}
|
||||
return _len - len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate contents of the buffer from userspace related to OS descriptors.
|
||||
*/
|
||||
static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
|
||||
struct usb_os_desc_header *h, void *data,
|
||||
unsigned len, void *priv)
|
||||
{
|
||||
struct ffs_data *ffs = priv;
|
||||
u8 length;
|
||||
|
||||
ENTER();
|
||||
|
||||
switch (type) {
|
||||
case FFS_OS_DESC_EXT_COMPAT: {
|
||||
struct usb_ext_compat_desc *d = data;
|
||||
int i;
|
||||
|
||||
if (len < sizeof(*d) ||
|
||||
d->bFirstInterfaceNumber >= ffs->interfaces_count ||
|
||||
d->Reserved1)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
|
||||
if (d->Reserved2[i])
|
||||
return -EINVAL;
|
||||
|
||||
length = sizeof(struct usb_ext_compat_desc);
|
||||
}
|
||||
break;
|
||||
case FFS_OS_DESC_EXT_PROP: {
|
||||
struct usb_ext_prop_desc *d = data;
|
||||
u32 type, pdl;
|
||||
u16 pnl;
|
||||
|
||||
if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
|
||||
return -EINVAL;
|
||||
length = le32_to_cpu(d->dwSize);
|
||||
type = le32_to_cpu(d->dwPropertyDataType);
|
||||
if (type < USB_EXT_PROP_UNICODE ||
|
||||
type > USB_EXT_PROP_UNICODE_MULTI) {
|
||||
pr_vdebug("unsupported os descriptor property type: %d",
|
||||
type);
|
||||
return -EINVAL;
|
||||
}
|
||||
pnl = le16_to_cpu(d->wPropertyNameLength);
|
||||
pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
|
||||
if (length != 14 + pnl + pdl) {
|
||||
pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
|
||||
length, pnl, pdl, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
++ffs->ms_os_descs_ext_prop_count;
|
||||
/* property name reported to the host as "WCHAR"s */
|
||||
ffs->ms_os_descs_ext_prop_name_len += pnl * 2;
|
||||
ffs->ms_os_descs_ext_prop_data_len += pdl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_vdebug("unknown descriptor: %d\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
static int __ffs_data_got_descs(struct ffs_data *ffs,
|
||||
char *const _data, size_t len)
|
||||
{
|
||||
char *data = _data, *raw_descs;
|
||||
unsigned counts[3], flags;
|
||||
unsigned os_descs_count = 0, counts[3], flags;
|
||||
int ret = -EINVAL, i;
|
||||
|
||||
ENTER();
|
||||
|
@ -1879,7 +2069,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
|||
flags = get_unaligned_le32(data + 8);
|
||||
if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
|
||||
FUNCTIONFS_HAS_HS_DESC |
|
||||
FUNCTIONFS_HAS_SS_DESC)) {
|
||||
FUNCTIONFS_HAS_SS_DESC |
|
||||
FUNCTIONFS_HAS_MS_OS_DESC)) {
|
||||
ret = -ENOSYS;
|
||||
goto error;
|
||||
}
|
||||
|
@ -1902,6 +2093,11 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
|||
len -= 4;
|
||||
}
|
||||
}
|
||||
if (flags & (1 << i)) {
|
||||
os_descs_count = get_unaligned_le32(data);
|
||||
data += 4;
|
||||
len -= 4;
|
||||
};
|
||||
|
||||
/* Read descriptors */
|
||||
raw_descs = data;
|
||||
|
@ -1915,6 +2111,14 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
|||
data += ret;
|
||||
len -= ret;
|
||||
}
|
||||
if (os_descs_count) {
|
||||
ret = ffs_do_os_descs(os_descs_count, data, len,
|
||||
__ffs_data_do_os_desc, ffs);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
data += ret;
|
||||
len -= ret;
|
||||
}
|
||||
|
||||
if (raw_descs == data || len) {
|
||||
ret = -EINVAL;
|
||||
|
@ -1927,6 +2131,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
|||
ffs->fs_descs_count = counts[0];
|
||||
ffs->hs_descs_count = counts[1];
|
||||
ffs->ss_descs_count = counts[2];
|
||||
ffs->ms_os_descs_count = os_descs_count;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2268,6 +2473,85 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __ffs_func_bind_do_os_desc(enum ffs_os_desc_type type,
|
||||
struct usb_os_desc_header *h, void *data,
|
||||
unsigned len, void *priv)
|
||||
{
|
||||
struct ffs_function *func = priv;
|
||||
u8 length = 0;
|
||||
|
||||
switch (type) {
|
||||
case FFS_OS_DESC_EXT_COMPAT: {
|
||||
struct usb_ext_compat_desc *desc = data;
|
||||
struct usb_os_desc_table *t;
|
||||
|
||||
t = &func->function.os_desc_table[desc->bFirstInterfaceNumber];
|
||||
t->if_id = func->interfaces_nums[desc->bFirstInterfaceNumber];
|
||||
memcpy(t->os_desc->ext_compat_id, &desc->CompatibleID,
|
||||
ARRAY_SIZE(desc->CompatibleID) +
|
||||
ARRAY_SIZE(desc->SubCompatibleID));
|
||||
length = sizeof(*desc);
|
||||
}
|
||||
break;
|
||||
case FFS_OS_DESC_EXT_PROP: {
|
||||
struct usb_ext_prop_desc *desc = data;
|
||||
struct usb_os_desc_table *t;
|
||||
struct usb_os_desc_ext_prop *ext_prop;
|
||||
char *ext_prop_name;
|
||||
char *ext_prop_data;
|
||||
|
||||
t = &func->function.os_desc_table[h->interface];
|
||||
t->if_id = func->interfaces_nums[h->interface];
|
||||
|
||||
ext_prop = func->ffs->ms_os_descs_ext_prop_avail;
|
||||
func->ffs->ms_os_descs_ext_prop_avail += sizeof(*ext_prop);
|
||||
|
||||
ext_prop->type = le32_to_cpu(desc->dwPropertyDataType);
|
||||
ext_prop->name_len = le16_to_cpu(desc->wPropertyNameLength);
|
||||
ext_prop->data_len = le32_to_cpu(*(u32 *)
|
||||
usb_ext_prop_data_len_ptr(data, ext_prop->name_len));
|
||||
length = ext_prop->name_len + ext_prop->data_len + 14;
|
||||
|
||||
ext_prop_name = func->ffs->ms_os_descs_ext_prop_name_avail;
|
||||
func->ffs->ms_os_descs_ext_prop_name_avail +=
|
||||
ext_prop->name_len;
|
||||
|
||||
ext_prop_data = func->ffs->ms_os_descs_ext_prop_data_avail;
|
||||
func->ffs->ms_os_descs_ext_prop_data_avail +=
|
||||
ext_prop->data_len;
|
||||
memcpy(ext_prop_data,
|
||||
usb_ext_prop_data_ptr(data, ext_prop->name_len),
|
||||
ext_prop->data_len);
|
||||
/* unicode data reported to the host as "WCHAR"s */
|
||||
switch (ext_prop->type) {
|
||||
case USB_EXT_PROP_UNICODE:
|
||||
case USB_EXT_PROP_UNICODE_ENV:
|
||||
case USB_EXT_PROP_UNICODE_LINK:
|
||||
case USB_EXT_PROP_UNICODE_MULTI:
|
||||
ext_prop->data_len *= 2;
|
||||
break;
|
||||
}
|
||||
ext_prop->data = ext_prop_data;
|
||||
|
||||
memcpy(ext_prop_name, usb_ext_prop_name_ptr(data),
|
||||
ext_prop->name_len);
|
||||
/* property name reported to the host as "WCHAR"s */
|
||||
ext_prop->name_len *= 2;
|
||||
ext_prop->name = ext_prop_name;
|
||||
|
||||
t->os_desc->ext_prop_len +=
|
||||
ext_prop->name_len + ext_prop->data_len + 14;
|
||||
++t->os_desc->ext_prop_count;
|
||||
list_add_tail(&ext_prop->entry, &t->os_desc->ext_prop);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_vdebug("unknown descriptor: %d\n", type);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
|
||||
struct usb_configuration *c)
|
||||
{
|
||||
|
@ -2329,7 +2613,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
|||
const int super = gadget_is_superspeed(func->gadget) &&
|
||||
func->ffs->ss_descs_count;
|
||||
|
||||
int fs_len, hs_len, ret;
|
||||
int fs_len, hs_len, ss_len, ret, i;
|
||||
|
||||
/* Make it a single chunk, less management later on */
|
||||
vla_group(d);
|
||||
|
@ -2341,6 +2625,18 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
|||
vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
|
||||
super ? ffs->ss_descs_count + 1 : 0);
|
||||
vla_item_with_sz(d, short, inums, ffs->interfaces_count);
|
||||
vla_item_with_sz(d, struct usb_os_desc_table, os_desc_table,
|
||||
c->cdev->use_os_string ? ffs->interfaces_count : 0);
|
||||
vla_item_with_sz(d, char[16], ext_compat,
|
||||
c->cdev->use_os_string ? ffs->interfaces_count : 0);
|
||||
vla_item_with_sz(d, struct usb_os_desc, os_desc,
|
||||
c->cdev->use_os_string ? ffs->interfaces_count : 0);
|
||||
vla_item_with_sz(d, struct usb_os_desc_ext_prop, ext_prop,
|
||||
ffs->ms_os_descs_ext_prop_count);
|
||||
vla_item_with_sz(d, char, ext_prop_name,
|
||||
ffs->ms_os_descs_ext_prop_name_len);
|
||||
vla_item_with_sz(d, char, ext_prop_data,
|
||||
ffs->ms_os_descs_ext_prop_data_len);
|
||||
vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
|
||||
char *vlabuf;
|
||||
|
||||
|
@ -2351,12 +2647,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
|||
return -ENOTSUPP;
|
||||
|
||||
/* Allocate a single chunk, less management later on */
|
||||
vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
|
||||
vlabuf = kzalloc(vla_group_size(d), GFP_KERNEL);
|
||||
if (unlikely(!vlabuf))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Zero */
|
||||
memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz);
|
||||
ffs->ms_os_descs_ext_prop_avail = vla_ptr(vlabuf, d, ext_prop);
|
||||
ffs->ms_os_descs_ext_prop_name_avail =
|
||||
vla_ptr(vlabuf, d, ext_prop_name);
|
||||
ffs->ms_os_descs_ext_prop_data_avail =
|
||||
vla_ptr(vlabuf, d, ext_prop_data);
|
||||
|
||||
/* Copy descriptors */
|
||||
memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
|
||||
ffs->raw_descs_length);
|
||||
|
@ -2410,12 +2710,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
|||
|
||||
if (likely(super)) {
|
||||
func->function.ss_descriptors = vla_ptr(vlabuf, d, ss_descs);
|
||||
ret = ffs_do_descs(ffs->ss_descs_count,
|
||||
ss_len = ffs_do_descs(ffs->ss_descs_count,
|
||||
vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
|
||||
d_raw_descs__sz - fs_len - hs_len,
|
||||
__ffs_func_bind_do_descs, func);
|
||||
if (unlikely(ret < 0))
|
||||
if (unlikely(ss_len < 0)) {
|
||||
ret = ss_len;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
ss_len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2431,6 +2735,28 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
|||
if (unlikely(ret < 0))
|
||||
goto error;
|
||||
|
||||
func->function.os_desc_table = vla_ptr(vlabuf, d, os_desc_table);
|
||||
if (c->cdev->use_os_string)
|
||||
for (i = 0; i < ffs->interfaces_count; ++i) {
|
||||
struct usb_os_desc *desc;
|
||||
|
||||
desc = func->function.os_desc_table[i].os_desc =
|
||||
vla_ptr(vlabuf, d, os_desc) +
|
||||
i * sizeof(struct usb_os_desc);
|
||||
desc->ext_compat_id =
|
||||
vla_ptr(vlabuf, d, ext_compat) + i * 16;
|
||||
INIT_LIST_HEAD(&desc->ext_prop);
|
||||
}
|
||||
ret = ffs_do_os_descs(ffs->ms_os_descs_count,
|
||||
vla_ptr(vlabuf, d, raw_descs) +
|
||||
fs_len + hs_len + ss_len,
|
||||
d_raw_descs__sz - fs_len - hs_len - ss_len,
|
||||
__ffs_func_bind_do_os_desc, func);
|
||||
if (unlikely(ret < 0))
|
||||
goto error;
|
||||
func->function.os_desc_n =
|
||||
c->cdev->use_os_string ? ffs->interfaces_count : 0;
|
||||
|
||||
/* And we're done */
|
||||
ffs_event_add(ffs, FUNCTIONFS_BIND);
|
||||
return 0;
|
||||
|
@ -2901,12 +3227,12 @@ static void *ffs_acquire_dev(const char *dev_name)
|
|||
|
||||
ffs_dev = _ffs_find_dev(dev_name);
|
||||
if (!ffs_dev)
|
||||
ffs_dev = ERR_PTR(-ENODEV);
|
||||
ffs_dev = ERR_PTR(-ENOENT);
|
||||
else if (ffs_dev->mounted)
|
||||
ffs_dev = ERR_PTR(-EBUSY);
|
||||
else if (ffs_dev->ffs_acquire_dev_callback &&
|
||||
ffs_dev->ffs_acquire_dev_callback(ffs_dev))
|
||||
ffs_dev = ERR_PTR(-ENODEV);
|
||||
ffs_dev = ERR_PTR(-ENOENT);
|
||||
else
|
||||
ffs_dev->mounted = true;
|
||||
|
|
@ -68,6 +68,18 @@ struct f_ncm {
|
|||
* callback and ethernet open/close
|
||||
*/
|
||||
spinlock_t lock;
|
||||
|
||||
struct net_device *netdev;
|
||||
|
||||
/* For multi-frame NDP TX */
|
||||
struct sk_buff *skb_tx_data;
|
||||
struct sk_buff *skb_tx_ndp;
|
||||
u16 ndp_dgram_count;
|
||||
bool timer_force_tx;
|
||||
struct tasklet_struct tx_tasklet;
|
||||
struct hrtimer task_timer;
|
||||
|
||||
bool timer_stopping;
|
||||
};
|
||||
|
||||
static inline struct f_ncm *func_to_ncm(struct usb_function *f)
|
||||
|
@ -92,15 +104,20 @@ static inline unsigned ncm_bitrate(struct usb_gadget *g)
|
|||
* If the host can group frames, allow it to do that, 16K is selected,
|
||||
* because it's used by default by the current linux host driver
|
||||
*/
|
||||
#define NTB_DEFAULT_IN_SIZE USB_CDC_NCM_NTB_MIN_IN_SIZE
|
||||
#define NTB_DEFAULT_IN_SIZE 16384
|
||||
#define NTB_OUT_SIZE 16384
|
||||
|
||||
/*
|
||||
* skbs of size less than that will not be aligned
|
||||
* to NCM's dwNtbInMaxSize to save bus bandwidth
|
||||
/* Allocation for storing the NDP, 32 should suffice for a
|
||||
* 16k packet. This allows a maximum of 32 * 507 Byte packets to
|
||||
* be transmitted in a single 16kB skb, though when sending full size
|
||||
* packets this limit will be plenty.
|
||||
* Smaller packets are not likely to be trying to maximize the
|
||||
* throughput and will be mstly sending smaller infrequent frames.
|
||||
*/
|
||||
#define TX_MAX_NUM_DPE 32
|
||||
|
||||
#define MAX_TX_NONFIXED (512 * 3)
|
||||
/* Delay for the transmit to wait before sending an unfilled NTB frame. */
|
||||
#define TX_TIMEOUT_NSECS 300000
|
||||
|
||||
#define FORMATS_SUPPORTED (USB_CDC_NCM_NTB16_SUPPORTED | \
|
||||
USB_CDC_NCM_NTB32_SUPPORTED)
|
||||
|
@ -355,14 +372,15 @@ struct ndp_parser_opts {
|
|||
u32 ndp_sign;
|
||||
unsigned nth_size;
|
||||
unsigned ndp_size;
|
||||
unsigned dpe_size;
|
||||
unsigned ndplen_align;
|
||||
/* sizes in u16 units */
|
||||
unsigned dgram_item_len; /* index or length */
|
||||
unsigned block_length;
|
||||
unsigned fp_index;
|
||||
unsigned ndp_index;
|
||||
unsigned reserved1;
|
||||
unsigned reserved2;
|
||||
unsigned next_fp_index;
|
||||
unsigned next_ndp_index;
|
||||
};
|
||||
|
||||
#define INIT_NDP16_OPTS { \
|
||||
|
@ -370,13 +388,14 @@ struct ndp_parser_opts {
|
|||
.ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \
|
||||
.nth_size = sizeof(struct usb_cdc_ncm_nth16), \
|
||||
.ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \
|
||||
.dpe_size = sizeof(struct usb_cdc_ncm_dpe16), \
|
||||
.ndplen_align = 4, \
|
||||
.dgram_item_len = 1, \
|
||||
.block_length = 1, \
|
||||
.fp_index = 1, \
|
||||
.ndp_index = 1, \
|
||||
.reserved1 = 0, \
|
||||
.reserved2 = 0, \
|
||||
.next_fp_index = 1, \
|
||||
.next_ndp_index = 1, \
|
||||
}
|
||||
|
||||
|
||||
|
@ -385,13 +404,14 @@ struct ndp_parser_opts {
|
|||
.ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \
|
||||
.nth_size = sizeof(struct usb_cdc_ncm_nth32), \
|
||||
.ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \
|
||||
.dpe_size = sizeof(struct usb_cdc_ncm_dpe32), \
|
||||
.ndplen_align = 8, \
|
||||
.dgram_item_len = 2, \
|
||||
.block_length = 2, \
|
||||
.fp_index = 2, \
|
||||
.ndp_index = 2, \
|
||||
.reserved1 = 1, \
|
||||
.reserved2 = 2, \
|
||||
.next_fp_index = 2, \
|
||||
.next_ndp_index = 2, \
|
||||
}
|
||||
|
||||
static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
|
||||
|
@ -803,6 +823,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
|||
|
||||
if (ncm->port.in_ep->driver_data) {
|
||||
DBG(cdev, "reset ncm\n");
|
||||
ncm->timer_stopping = true;
|
||||
ncm->netdev = NULL;
|
||||
gether_disconnect(&ncm->port);
|
||||
ncm_reset_values(ncm);
|
||||
}
|
||||
|
@ -839,6 +861,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
|||
net = gether_connect(&ncm->port);
|
||||
if (IS_ERR(net))
|
||||
return PTR_ERR(net);
|
||||
ncm->netdev = net;
|
||||
ncm->timer_stopping = false;
|
||||
}
|
||||
|
||||
spin_lock(&ncm->lock);
|
||||
|
@ -865,95 +889,232 @@ static int ncm_get_alt(struct usb_function *f, unsigned intf)
|
|||
return ncm->port.in_ep->driver_data ? 1 : 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *package_for_tx(struct f_ncm *ncm)
|
||||
{
|
||||
__le16 *ntb_iter;
|
||||
struct sk_buff *skb2 = NULL;
|
||||
unsigned ndp_pad;
|
||||
unsigned ndp_index;
|
||||
unsigned new_len;
|
||||
|
||||
const struct ndp_parser_opts *opts = ncm->parser_opts;
|
||||
const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
|
||||
const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
|
||||
|
||||
/* Stop the timer */
|
||||
hrtimer_try_to_cancel(&ncm->task_timer);
|
||||
|
||||
ndp_pad = ALIGN(ncm->skb_tx_data->len, ndp_align) -
|
||||
ncm->skb_tx_data->len;
|
||||
ndp_index = ncm->skb_tx_data->len + ndp_pad;
|
||||
new_len = ndp_index + dgram_idx_len + ncm->skb_tx_ndp->len;
|
||||
|
||||
/* Set the final BlockLength and wNdpIndex */
|
||||
ntb_iter = (void *) ncm->skb_tx_data->data;
|
||||
/* Increment pointer to BlockLength */
|
||||
ntb_iter += 2 + 1 + 1;
|
||||
put_ncm(&ntb_iter, opts->block_length, new_len);
|
||||
put_ncm(&ntb_iter, opts->ndp_index, ndp_index);
|
||||
|
||||
/* Set the final NDP wLength */
|
||||
new_len = opts->ndp_size +
|
||||
(ncm->ndp_dgram_count * dgram_idx_len);
|
||||
ncm->ndp_dgram_count = 0;
|
||||
/* Increment from start to wLength */
|
||||
ntb_iter = (void *) ncm->skb_tx_ndp->data;
|
||||
ntb_iter += 2;
|
||||
put_unaligned_le16(new_len, ntb_iter);
|
||||
|
||||
/* Merge the skbs */
|
||||
swap(skb2, ncm->skb_tx_data);
|
||||
if (ncm->skb_tx_data) {
|
||||
dev_kfree_skb_any(ncm->skb_tx_data);
|
||||
ncm->skb_tx_data = NULL;
|
||||
}
|
||||
|
||||
/* Insert NDP alignment. */
|
||||
ntb_iter = (void *) skb_put(skb2, ndp_pad);
|
||||
memset(ntb_iter, 0, ndp_pad);
|
||||
|
||||
/* Copy NTB across. */
|
||||
ntb_iter = (void *) skb_put(skb2, ncm->skb_tx_ndp->len);
|
||||
memcpy(ntb_iter, ncm->skb_tx_ndp->data, ncm->skb_tx_ndp->len);
|
||||
dev_kfree_skb_any(ncm->skb_tx_ndp);
|
||||
ncm->skb_tx_ndp = NULL;
|
||||
|
||||
/* Insert zero'd datagram. */
|
||||
ntb_iter = (void *) skb_put(skb2, dgram_idx_len);
|
||||
memset(ntb_iter, 0, dgram_idx_len);
|
||||
|
||||
return skb2;
|
||||
}
|
||||
|
||||
static struct sk_buff *ncm_wrap_ntb(struct gether *port,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct f_ncm *ncm = func_to_ncm(&port->func);
|
||||
struct sk_buff *skb2;
|
||||
struct sk_buff *skb2 = NULL;
|
||||
int ncb_len = 0;
|
||||
__le16 *tmp;
|
||||
int div;
|
||||
int rem;
|
||||
int pad;
|
||||
int ndp_align;
|
||||
int ndp_pad;
|
||||
__le16 *ntb_data;
|
||||
__le16 *ntb_ndp;
|
||||
int dgram_pad;
|
||||
|
||||
unsigned max_size = ncm->port.fixed_in_len;
|
||||
const struct ndp_parser_opts *opts = ncm->parser_opts;
|
||||
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
|
||||
const int ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
|
||||
const int div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
|
||||
const int rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
|
||||
const int dgram_idx_len = 2 * 2 * opts->dgram_item_len;
|
||||
|
||||
div = le16_to_cpu(ntb_parameters.wNdpInDivisor);
|
||||
rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
|
||||
ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
|
||||
if (!skb && !ncm->skb_tx_data)
|
||||
return NULL;
|
||||
|
||||
ncb_len += opts->nth_size;
|
||||
ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
|
||||
ncb_len += ndp_pad;
|
||||
ncb_len += opts->ndp_size;
|
||||
ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */
|
||||
ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */
|
||||
pad = ALIGN(ncb_len, div) + rem - ncb_len;
|
||||
ncb_len += pad;
|
||||
if (skb) {
|
||||
/* Add the CRC if required up front */
|
||||
if (ncm->is_crc) {
|
||||
uint32_t crc;
|
||||
__le16 *crc_pos;
|
||||
|
||||
if (ncb_len + skb->len + crc_len > max_size) {
|
||||
crc = ~crc32_le(~0,
|
||||
skb->data,
|
||||
skb->len);
|
||||
crc_pos = (void *) skb_put(skb, sizeof(uint32_t));
|
||||
put_unaligned_le32(crc, crc_pos);
|
||||
}
|
||||
|
||||
/* If the new skb is too big for the current NCM NTB then
|
||||
* set the current stored skb to be sent now and clear it
|
||||
* ready for new data.
|
||||
* NOTE: Assume maximum align for speed of calculation.
|
||||
*/
|
||||
if (ncm->skb_tx_data
|
||||
&& (ncm->ndp_dgram_count >= TX_MAX_NUM_DPE
|
||||
|| (ncm->skb_tx_data->len +
|
||||
div + rem + skb->len +
|
||||
ncm->skb_tx_ndp->len + ndp_align + (2 * dgram_idx_len))
|
||||
> max_size)) {
|
||||
skb2 = package_for_tx(ncm);
|
||||
if (!skb2)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ncm->skb_tx_data) {
|
||||
ncb_len = opts->nth_size;
|
||||
dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
|
||||
ncb_len += dgram_pad;
|
||||
|
||||
/* Create a new skb for the NTH and datagrams. */
|
||||
ncm->skb_tx_data = alloc_skb(max_size, GFP_ATOMIC);
|
||||
if (!ncm->skb_tx_data)
|
||||
goto err;
|
||||
|
||||
ntb_data = (void *) skb_put(ncm->skb_tx_data, ncb_len);
|
||||
memset(ntb_data, 0, ncb_len);
|
||||
/* dwSignature */
|
||||
put_unaligned_le32(opts->nth_sign, ntb_data);
|
||||
ntb_data += 2;
|
||||
/* wHeaderLength */
|
||||
put_unaligned_le16(opts->nth_size, ntb_data++);
|
||||
|
||||
/* Allocate an skb for storing the NDP,
|
||||
* TX_MAX_NUM_DPE should easily suffice for a
|
||||
* 16k packet.
|
||||
*/
|
||||
ncm->skb_tx_ndp = alloc_skb((int)(opts->ndp_size
|
||||
+ opts->dpe_size
|
||||
* TX_MAX_NUM_DPE),
|
||||
GFP_ATOMIC);
|
||||
if (!ncm->skb_tx_ndp)
|
||||
goto err;
|
||||
ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp,
|
||||
opts->ndp_size);
|
||||
memset(ntb_ndp, 0, ncb_len);
|
||||
/* dwSignature */
|
||||
put_unaligned_le32(ncm->ndp_sign, ntb_ndp);
|
||||
ntb_ndp += 2;
|
||||
|
||||
/* There is always a zeroed entry */
|
||||
ncm->ndp_dgram_count = 1;
|
||||
|
||||
/* Note: we skip opts->next_ndp_index */
|
||||
}
|
||||
|
||||
/* Delay the timer. */
|
||||
hrtimer_start(&ncm->task_timer,
|
||||
ktime_set(0, TX_TIMEOUT_NSECS),
|
||||
HRTIMER_MODE_REL);
|
||||
|
||||
/* Add the datagram position entries */
|
||||
ntb_ndp = (void *) skb_put(ncm->skb_tx_ndp, dgram_idx_len);
|
||||
memset(ntb_ndp, 0, dgram_idx_len);
|
||||
|
||||
ncb_len = ncm->skb_tx_data->len;
|
||||
dgram_pad = ALIGN(ncb_len, div) + rem - ncb_len;
|
||||
ncb_len += dgram_pad;
|
||||
|
||||
/* (d)wDatagramIndex */
|
||||
put_ncm(&ntb_ndp, opts->dgram_item_len, ncb_len);
|
||||
/* (d)wDatagramLength */
|
||||
put_ncm(&ntb_ndp, opts->dgram_item_len, skb->len);
|
||||
ncm->ndp_dgram_count++;
|
||||
|
||||
/* Add the new data to the skb */
|
||||
ntb_data = (void *) skb_put(ncm->skb_tx_data, dgram_pad);
|
||||
memset(ntb_data, 0, dgram_pad);
|
||||
ntb_data = (void *) skb_put(ncm->skb_tx_data, skb->len);
|
||||
memcpy(ntb_data, skb->data, skb->len);
|
||||
dev_kfree_skb_any(skb);
|
||||
return NULL;
|
||||
skb = NULL;
|
||||
|
||||
} else if (ncm->skb_tx_data && ncm->timer_force_tx) {
|
||||
/* If the tx was requested because of a timeout then send */
|
||||
skb2 = package_for_tx(ncm);
|
||||
if (!skb2)
|
||||
goto err;
|
||||
}
|
||||
|
||||
skb2 = skb_copy_expand(skb, ncb_len,
|
||||
max_size - skb->len - ncb_len - crc_len,
|
||||
GFP_ATOMIC);
|
||||
dev_kfree_skb_any(skb);
|
||||
if (!skb2)
|
||||
return NULL;
|
||||
return skb2;
|
||||
|
||||
skb = skb2;
|
||||
err:
|
||||
ncm->netdev->stats.tx_dropped++;
|
||||
|
||||
tmp = (void *) skb_push(skb, ncb_len);
|
||||
memset(tmp, 0, ncb_len);
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
if (ncm->skb_tx_data)
|
||||
dev_kfree_skb_any(ncm->skb_tx_data);
|
||||
if (ncm->skb_tx_ndp)
|
||||
dev_kfree_skb_any(ncm->skb_tx_ndp);
|
||||
|
||||
put_unaligned_le32(opts->nth_sign, tmp); /* dwSignature */
|
||||
tmp += 2;
|
||||
/* wHeaderLength */
|
||||
put_unaligned_le16(opts->nth_size, tmp++);
|
||||
tmp++; /* skip wSequence */
|
||||
put_ncm(&tmp, opts->block_length, skb->len); /* (d)wBlockLength */
|
||||
/* (d)wFpIndex */
|
||||
/* the first pointer is right after the NTH + align */
|
||||
put_ncm(&tmp, opts->fp_index, opts->nth_size + ndp_pad);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tmp = (void *)tmp + ndp_pad;
|
||||
/*
|
||||
* This transmits the NTB if there are frames waiting.
|
||||
*/
|
||||
static void ncm_tx_tasklet(unsigned long data)
|
||||
{
|
||||
struct f_ncm *ncm = (void *)data;
|
||||
|
||||
/* NDP */
|
||||
put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */
|
||||
tmp += 2;
|
||||
/* wLength */
|
||||
put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
|
||||
if (ncm->timer_stopping)
|
||||
return;
|
||||
|
||||
tmp += opts->reserved1;
|
||||
tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
|
||||
tmp += opts->reserved2;
|
||||
|
||||
if (ncm->is_crc) {
|
||||
uint32_t crc;
|
||||
|
||||
crc = ~crc32_le(~0,
|
||||
skb->data + ncb_len,
|
||||
skb->len - ncb_len);
|
||||
put_unaligned_le32(crc, skb->data + skb->len);
|
||||
skb_put(skb, crc_len);
|
||||
/* Only send if data is available. */
|
||||
if (ncm->skb_tx_data) {
|
||||
ncm->timer_force_tx = true;
|
||||
ncm->netdev->netdev_ops->ndo_start_xmit(NULL, ncm->netdev);
|
||||
ncm->timer_force_tx = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* (d)wDatagramIndex[0] */
|
||||
put_ncm(&tmp, opts->dgram_item_len, ncb_len);
|
||||
/* (d)wDatagramLength[0] */
|
||||
put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len);
|
||||
/* (d)wDatagramIndex[1] and (d)wDatagramLength[1] already zeroed */
|
||||
|
||||
if (skb->len > MAX_TX_NONFIXED)
|
||||
memset(skb_put(skb, max_size - skb->len),
|
||||
0, max_size - skb->len);
|
||||
|
||||
return skb;
|
||||
/*
|
||||
* The transmit should only be run if no skb data has been sent
|
||||
* for a certain duration.
|
||||
*/
|
||||
static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
|
||||
{
|
||||
struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
|
||||
tasklet_schedule(&ncm->tx_tasklet);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static int ncm_unwrap_ntb(struct gether *port,
|
||||
|
@ -963,6 +1124,7 @@ static int ncm_unwrap_ntb(struct gether *port,
|
|||
struct f_ncm *ncm = func_to_ncm(&port->func);
|
||||
__le16 *tmp = (void *) skb->data;
|
||||
unsigned index, index2;
|
||||
int ndp_index;
|
||||
unsigned dg_len, dg_len2;
|
||||
unsigned ndp_len;
|
||||
struct sk_buff *skb2;
|
||||
|
@ -995,91 +1157,101 @@ static int ncm_unwrap_ntb(struct gether *port,
|
|||
goto err;
|
||||
}
|
||||
|
||||
index = get_ncm(&tmp, opts->fp_index);
|
||||
/* NCM 3.2 */
|
||||
if (((index % 4) != 0) && (index < opts->nth_size)) {
|
||||
INFO(port->func.config->cdev, "Bad index: %x\n",
|
||||
index);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* walk through NDP */
|
||||
tmp = ((void *)skb->data) + index;
|
||||
if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
|
||||
INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
|
||||
goto err;
|
||||
}
|
||||
tmp += 2;
|
||||
|
||||
ndp_len = get_unaligned_le16(tmp++);
|
||||
/*
|
||||
* NCM 3.3.1
|
||||
* entry is 2 items
|
||||
* item size is 16/32 bits, opts->dgram_item_len * 2 bytes
|
||||
* minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
|
||||
*/
|
||||
if ((ndp_len < opts->ndp_size + 2 * 2 * (opts->dgram_item_len * 2))
|
||||
|| (ndp_len % opts->ndplen_align != 0)) {
|
||||
INFO(port->func.config->cdev, "Bad NDP length: %x\n", ndp_len);
|
||||
goto err;
|
||||
}
|
||||
tmp += opts->reserved1;
|
||||
tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
|
||||
tmp += opts->reserved2;
|
||||
|
||||
ndp_len -= opts->ndp_size;
|
||||
index2 = get_ncm(&tmp, opts->dgram_item_len);
|
||||
dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
|
||||
dgram_counter = 0;
|
||||
ndp_index = get_ncm(&tmp, opts->ndp_index);
|
||||
|
||||
/* Run through all the NDP's in the NTB */
|
||||
do {
|
||||
index = index2;
|
||||
dg_len = dg_len2;
|
||||
if (dg_len < 14 + crc_len) { /* ethernet header + crc */
|
||||
INFO(port->func.config->cdev, "Bad dgram length: %x\n",
|
||||
dg_len);
|
||||
/* NCM 3.2 */
|
||||
if (((ndp_index % 4) != 0) &&
|
||||
(ndp_index < opts->nth_size)) {
|
||||
INFO(port->func.config->cdev, "Bad index: %#X\n",
|
||||
ndp_index);
|
||||
goto err;
|
||||
}
|
||||
if (ncm->is_crc) {
|
||||
uint32_t crc, crc2;
|
||||
|
||||
crc = get_unaligned_le32(skb->data +
|
||||
index + dg_len - crc_len);
|
||||
crc2 = ~crc32_le(~0,
|
||||
skb->data + index,
|
||||
dg_len - crc_len);
|
||||
if (crc != crc2) {
|
||||
INFO(port->func.config->cdev, "Bad CRC\n");
|
||||
goto err;
|
||||
}
|
||||
/* walk through NDP */
|
||||
tmp = (void *)(skb->data + ndp_index);
|
||||
if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
|
||||
INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
|
||||
goto err;
|
||||
}
|
||||
tmp += 2;
|
||||
|
||||
ndp_len = get_unaligned_le16(tmp++);
|
||||
/*
|
||||
* NCM 3.3.1
|
||||
* entry is 2 items
|
||||
* item size is 16/32 bits, opts->dgram_item_len * 2 bytes
|
||||
* minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
|
||||
* Each entry is a dgram index and a dgram length.
|
||||
*/
|
||||
if ((ndp_len < opts->ndp_size
|
||||
+ 2 * 2 * (opts->dgram_item_len * 2))
|
||||
|| (ndp_len % opts->ndplen_align != 0)) {
|
||||
INFO(port->func.config->cdev, "Bad NDP length: %#X\n",
|
||||
ndp_len);
|
||||
goto err;
|
||||
}
|
||||
tmp += opts->reserved1;
|
||||
/* Check for another NDP (d)wNextNdpIndex */
|
||||
ndp_index = get_ncm(&tmp, opts->next_ndp_index);
|
||||
tmp += opts->reserved2;
|
||||
|
||||
ndp_len -= opts->ndp_size;
|
||||
index2 = get_ncm(&tmp, opts->dgram_item_len);
|
||||
dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
|
||||
dgram_counter = 0;
|
||||
|
||||
if (index2 == 0 || dg_len2 == 0) {
|
||||
skb2 = skb;
|
||||
} else {
|
||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
do {
|
||||
index = index2;
|
||||
dg_len = dg_len2;
|
||||
if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */
|
||||
INFO(port->func.config->cdev,
|
||||
"Bad dgram length: %#X\n", dg_len);
|
||||
goto err;
|
||||
}
|
||||
if (ncm->is_crc) {
|
||||
uint32_t crc, crc2;
|
||||
|
||||
crc = get_unaligned_le32(skb->data +
|
||||
index + dg_len -
|
||||
crc_len);
|
||||
crc2 = ~crc32_le(~0,
|
||||
skb->data + index,
|
||||
dg_len - crc_len);
|
||||
if (crc != crc2) {
|
||||
INFO(port->func.config->cdev,
|
||||
"Bad CRC\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
index2 = get_ncm(&tmp, opts->dgram_item_len);
|
||||
dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
|
||||
|
||||
/*
|
||||
* Copy the data into a new skb.
|
||||
* This ensures the truesize is correct
|
||||
*/
|
||||
skb2 = netdev_alloc_skb_ip_align(ncm->netdev,
|
||||
dg_len - crc_len);
|
||||
if (skb2 == NULL)
|
||||
goto err;
|
||||
}
|
||||
memcpy(skb_put(skb2, dg_len - crc_len),
|
||||
skb->data + index, dg_len - crc_len);
|
||||
|
||||
if (!skb_pull(skb2, index)) {
|
||||
ret = -EOVERFLOW;
|
||||
goto err;
|
||||
}
|
||||
skb_queue_tail(list, skb2);
|
||||
|
||||
skb_trim(skb2, dg_len - crc_len);
|
||||
skb_queue_tail(list, skb2);
|
||||
ndp_len -= 2 * (opts->dgram_item_len * 2);
|
||||
|
||||
ndp_len -= 2 * (opts->dgram_item_len * 2);
|
||||
dgram_counter++;
|
||||
|
||||
dgram_counter++;
|
||||
if (index2 == 0 || dg_len2 == 0)
|
||||
break;
|
||||
} while (ndp_len > 2 * (opts->dgram_item_len * 2));
|
||||
} while (ndp_index);
|
||||
|
||||
if (index2 == 0 || dg_len2 == 0)
|
||||
break;
|
||||
} while (ndp_len > 2 * (opts->dgram_item_len * 2)); /* zero entry */
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
VDBG(port->func.config->cdev,
|
||||
"Parsed NTB with %d frames\n", dgram_counter);
|
||||
|
@ -1097,8 +1269,11 @@ static void ncm_disable(struct usb_function *f)
|
|||
|
||||
DBG(cdev, "ncm deactivated\n");
|
||||
|
||||
if (ncm->port.in_ep->driver_data)
|
||||
if (ncm->port.in_ep->driver_data) {
|
||||
ncm->timer_stopping = true;
|
||||
ncm->netdev = NULL;
|
||||
gether_disconnect(&ncm->port);
|
||||
}
|
||||
|
||||
if (ncm->notify->driver_data) {
|
||||
usb_ep_disable(ncm->notify);
|
||||
|
@ -1267,6 +1442,10 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
ncm->port.open = ncm_open;
|
||||
ncm->port.close = ncm_close;
|
||||
|
||||
tasklet_init(&ncm->tx_tasklet, ncm_tx_tasklet, (unsigned long) ncm);
|
||||
hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
ncm->task_timer.function = ncm_tx_timeout;
|
||||
|
||||
DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
|
||||
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||
ncm->port.in_ep->name, ncm->port.out_ep->name,
|
||||
|
@ -1380,6 +1559,10 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
|
|||
|
||||
DBG(c->cdev, "ncm unbind\n");
|
||||
|
||||
hrtimer_cancel(&ncm->task_timer);
|
||||
tasklet_kill(&ncm->tx_tasklet);
|
||||
|
||||
ncm_string_defs[0].id = 0;
|
||||
usb_free_all_descriptors(f);
|
||||
|
||||
kfree(ncm->notify_req->buf);
|
||||
|
@ -1416,6 +1599,7 @@ static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
|
|||
ncm->port.ioport = netdev_priv(opts->net);
|
||||
mutex_unlock(&opts->lock);
|
||||
ncm->port.is_fixed = true;
|
||||
ncm->port.supports_multi_frame = true;
|
||||
|
||||
ncm->port.func.name = "cdc_network";
|
||||
/* descriptors are per-instance copies */
|
|
@ -727,6 +727,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
rndis_control_intf.bInterfaceNumber = status;
|
||||
rndis_union_desc.bMasterInterface0 = status;
|
||||
|
||||
if (cdev->use_os_string)
|
||||
f->os_desc_table[0].if_id =
|
||||
rndis_iad_descriptor.bFirstInterface;
|
||||
|
||||
status = usb_interface_id(c, f);
|
||||
if (status < 0)
|
||||
goto fail;
|
|
@ -348,14 +348,34 @@ static int uac2_pcm_open(struct snd_pcm_substream *substream)
|
|||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
spin_lock_init(&uac2->p_prm.lock);
|
||||
runtime->hw.rate_min = p_srate;
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! p_ssize ! */
|
||||
switch (p_ssize) {
|
||||
case 3:
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
|
||||
break;
|
||||
case 4:
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
|
||||
break;
|
||||
default:
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
|
||||
break;
|
||||
}
|
||||
runtime->hw.channels_min = num_channels(p_chmask);
|
||||
runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
|
||||
/ runtime->hw.periods_min;
|
||||
} else {
|
||||
spin_lock_init(&uac2->c_prm.lock);
|
||||
runtime->hw.rate_min = c_srate;
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; /* ! c_ssize ! */
|
||||
switch (c_ssize) {
|
||||
case 3:
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
|
||||
break;
|
||||
case 4:
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
|
||||
break;
|
||||
default:
|
||||
runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
|
||||
break;
|
||||
}
|
||||
runtime->hw.channels_min = num_channels(c_chmask);
|
||||
runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
|
||||
/ runtime->hw.periods_min;
|
|
@ -483,7 +483,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
|
|||
struct net_device *net)
|
||||
{
|
||||
struct eth_dev *dev = netdev_priv(net);
|
||||
int length = skb->len;
|
||||
int length = 0;
|
||||
int retval;
|
||||
struct usb_request *req = NULL;
|
||||
unsigned long flags;
|
||||
|
@ -500,13 +500,13 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
|
|||
}
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
if (!in) {
|
||||
if (skb && !in) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/* apply outgoing CDC or RNDIS filters */
|
||||
if (!is_promisc(cdc_filter)) {
|
||||
if (skb && !is_promisc(cdc_filter)) {
|
||||
u8 *dest = skb->data;
|
||||
|
||||
if (is_multicast_ether_addr(dest)) {
|
||||
|
@ -557,11 +557,17 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
|
|||
if (dev->port_usb)
|
||||
skb = dev->wrap(dev->port_usb, skb);
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
if (!skb)
|
||||
if (!skb) {
|
||||
/* Multi frame CDC protocols may store the frame for
|
||||
* later which is not a dropped frame.
|
||||
*/
|
||||
if (dev->port_usb->supports_multi_frame)
|
||||
goto multiframe;
|
||||
goto drop;
|
||||
|
||||
length = skb->len;
|
||||
}
|
||||
}
|
||||
|
||||
length = skb->len;
|
||||
req->buf = skb->data;
|
||||
req->context = skb;
|
||||
req->complete = tx_complete;
|
||||
|
@ -604,6 +610,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
|
|||
dev_kfree_skb_any(skb);
|
||||
drop:
|
||||
dev->net->stats.tx_dropped++;
|
||||
multiframe:
|
||||
spin_lock_irqsave(&dev->req_lock, flags);
|
||||
if (list_empty(&dev->tx_reqs))
|
||||
netif_start_queue(net);
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/if_ether.h>
|
||||
#include <linux/usb/composite.h>
|
||||
#include <linux/usb/cdc.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "gadget_chips.h"
|
||||
|
||||
|
@ -74,6 +75,7 @@ struct gether {
|
|||
bool is_fixed;
|
||||
u32 fixed_out_len;
|
||||
u32 fixed_in_len;
|
||||
bool supports_multi_frame;
|
||||
struct sk_buff *(*wrap)(struct gether *port,
|
||||
struct sk_buff *skb);
|
||||
int (*unwrap)(struct gether *port,
|
|
@ -216,6 +216,13 @@ struct ffs_data {
|
|||
unsigned fs_descs_count;
|
||||
unsigned hs_descs_count;
|
||||
unsigned ss_descs_count;
|
||||
unsigned ms_os_descs_count;
|
||||
unsigned ms_os_descs_ext_prop_count;
|
||||
unsigned ms_os_descs_ext_prop_name_len;
|
||||
unsigned ms_os_descs_ext_prop_data_len;
|
||||
void *ms_os_descs_ext_prop_avail;
|
||||
void *ms_os_descs_ext_prop_name_avail;
|
||||
void *ms_os_descs_ext_prop_data_avail;
|
||||
|
||||
unsigned short strings_count;
|
||||
unsigned short interfaces_count;
|
|
@ -0,0 +1,475 @@
|
|||
#
|
||||
# USB Gadget support on a system involves
|
||||
# (a) a peripheral controller, and
|
||||
# (b) the gadget driver using it.
|
||||
#
|
||||
# NOTE: Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
|
||||
#
|
||||
# - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
|
||||
# - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
|
||||
# - Some systems have both kinds of controllers.
|
||||
#
|
||||
# With help from a special transceiver and a "Mini-AB" jack, systems with
|
||||
# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
|
||||
#
|
||||
|
||||
config USB_ZERO
|
||||
tristate "Gadget Zero (DEVELOPMENT)"
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_SS_LB
|
||||
help
|
||||
Gadget Zero is a two-configuration device. It either sinks and
|
||||
sources bulk data; or it loops back a configurable number of
|
||||
transfers. It also implements control requests, for "chapter 9"
|
||||
conformance. The driver needs only two bulk-capable endpoints, so
|
||||
it can work on top of most device-side usb controllers. It's
|
||||
useful for testing, and is also a working example showing how
|
||||
USB "gadget drivers" can be written.
|
||||
|
||||
Make this be the first driver you try using on top of any new
|
||||
USB peripheral controller driver. Then you can use host-side
|
||||
test software, like the "usbtest" driver, to put your hardware
|
||||
and its driver through a basic set of functional tests.
|
||||
|
||||
Gadget Zero also works with the host-side "usb-skeleton" driver,
|
||||
and with many kinds of host-side test software. You may need
|
||||
to tweak product and vendor IDs before host software knows about
|
||||
this device, and arrange to select an appropriate configuration.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_zero".
|
||||
|
||||
config USB_ZERO_HNPTEST
|
||||
boolean "HNP Test Device"
|
||||
depends on USB_ZERO && USB_OTG
|
||||
help
|
||||
You can configure this device to enumerate using the device
|
||||
identifiers of the USB-OTG test device. That means that when
|
||||
this gadget connects to another OTG device, with this one using
|
||||
the "B-Peripheral" role, that device will use HNP to let this
|
||||
one serve as the USB host instead (in the "B-Host" role).
|
||||
|
||||
config USB_AUDIO
|
||||
tristate "Audio Gadget"
|
||||
depends on SND
|
||||
select USB_LIBCOMPOSITE
|
||||
select SND_PCM
|
||||
help
|
||||
This Gadget Audio driver is compatible with USB Audio Class
|
||||
specification 2.0. It implements 1 AudioControl interface,
|
||||
1 AudioStreaming Interface each for USB-OUT and USB-IN.
|
||||
Number of channels, sample rate and sample size can be
|
||||
specified as module parameters.
|
||||
This driver doesn't expect any real Audio codec to be present
|
||||
on the device - the audio streams are simply sinked to and
|
||||
sourced from a virtual ALSA sound card created. The user-space
|
||||
application may choose to do whatever it wants with the data
|
||||
received from the USB Host and choose to provide whatever it
|
||||
wants as audio data to the USB Host.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_audio".
|
||||
|
||||
config GADGET_UAC1
|
||||
bool "UAC 1.0 (Legacy)"
|
||||
depends on USB_AUDIO
|
||||
help
|
||||
If you instead want older UAC Spec-1.0 driver that also has audio
|
||||
paths hardwired to the Audio codec chip on-board and doesn't work
|
||||
without one.
|
||||
|
||||
config USB_ETH
|
||||
tristate "Ethernet Gadget (with CDC Ethernet support)"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_ETHER
|
||||
select USB_F_ECM
|
||||
select USB_F_SUBSET
|
||||
select CRC32
|
||||
help
|
||||
This driver implements Ethernet style communication, in one of
|
||||
several ways:
|
||||
|
||||
- The "Communication Device Class" (CDC) Ethernet Control Model.
|
||||
That protocol is often avoided with pure Ethernet adapters, in
|
||||
favor of simpler vendor-specific hardware, but is widely
|
||||
supported by firmware for smart network devices.
|
||||
|
||||
- On hardware can't implement that protocol, a simple CDC subset
|
||||
is used, placing fewer demands on USB.
|
||||
|
||||
- CDC Ethernet Emulation Model (EEM) is a newer standard that has
|
||||
a simpler interface that can be used by more USB hardware.
|
||||
|
||||
RNDIS support is an additional option, more demanding than than
|
||||
subset.
|
||||
|
||||
Within the USB device, this gadget driver exposes a network device
|
||||
"usbX", where X depends on what other networking devices you have.
|
||||
Treat it like a two-node Ethernet link: host, and gadget.
|
||||
|
||||
The Linux-USB host-side "usbnet" driver interoperates with this
|
||||
driver, so that deep I/O queues can be supported. On 2.4 kernels,
|
||||
use "CDCEther" instead, if you're using the CDC option. That CDC
|
||||
mode should also interoperate with standard CDC Ethernet class
|
||||
drivers on other host operating systems.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_ether".
|
||||
|
||||
config USB_ETH_RNDIS
|
||||
bool "RNDIS support"
|
||||
depends on USB_ETH
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_RNDIS
|
||||
default y
|
||||
help
|
||||
Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
|
||||
and Microsoft provides redistributable binary RNDIS drivers for
|
||||
older versions of Windows.
|
||||
|
||||
If you say "y" here, the Ethernet gadget driver will try to provide
|
||||
a second device configuration, supporting RNDIS to talk to such
|
||||
Microsoft USB hosts.
|
||||
|
||||
To make MS-Windows work with this, use Documentation/usb/linux.inf
|
||||
as the "driver info file". For versions of MS-Windows older than
|
||||
XP, you'll need to download drivers from Microsoft's website; a URL
|
||||
is given in comments found in that info file.
|
||||
|
||||
config USB_ETH_EEM
|
||||
bool "Ethernet Emulation Model (EEM) support"
|
||||
depends on USB_ETH
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_EEM
|
||||
default n
|
||||
help
|
||||
CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
|
||||
and therefore can be supported by more hardware. Technically ECM and
|
||||
EEM are designed for different applications. The ECM model extends
|
||||
the network interface to the target (e.g. a USB cable modem), and the
|
||||
EEM model is for mobile devices to communicate with hosts using
|
||||
ethernet over USB. For Linux gadgets, however, the interface with
|
||||
the host is the same (a usbX device), so the differences are minimal.
|
||||
|
||||
If you say "y" here, the Ethernet gadget driver will use the EEM
|
||||
protocol rather than ECM. If unsure, say "n".
|
||||
|
||||
config USB_G_NCM
|
||||
tristate "Network Control Model (NCM) support"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_ETHER
|
||||
select USB_F_NCM
|
||||
select CRC32
|
||||
help
|
||||
This driver implements USB CDC NCM subclass standard. NCM is
|
||||
an advanced protocol for Ethernet encapsulation, allows grouping
|
||||
of several ethernet frames into one USB transfer and different
|
||||
alignment possibilities.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_ncm".
|
||||
|
||||
config USB_GADGETFS
|
||||
tristate "Gadget Filesystem"
|
||||
help
|
||||
This driver provides a filesystem based API that lets user mode
|
||||
programs implement a single-configuration USB device, including
|
||||
endpoint I/O and control requests that don't relate to enumeration.
|
||||
All endpoints, transfer speeds, and transfer types supported by
|
||||
the hardware are available, through read() and write() calls.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "gadgetfs".
|
||||
|
||||
config USB_FUNCTIONFS
|
||||
tristate "Function Filesystem"
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_FS
|
||||
select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
|
||||
help
|
||||
The Function Filesystem (FunctionFS) lets one create USB
|
||||
composite functions in user space in the same way GadgetFS
|
||||
lets one create USB gadgets in user space. This allows creation
|
||||
of composite gadgets such that some of the functions are
|
||||
implemented in kernel space (for instance Ethernet, serial or
|
||||
mass storage) and other are implemented in user space.
|
||||
|
||||
If you say "y" or "m" here you will be able what kind of
|
||||
configurations the gadget will provide.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build
|
||||
a dynamically linked module called "g_ffs".
|
||||
|
||||
config USB_FUNCTIONFS_ETH
|
||||
bool "Include configuration with CDC ECM (Ethernet)"
|
||||
depends on USB_FUNCTIONFS && NET
|
||||
select USB_U_ETHER
|
||||
select USB_F_ECM
|
||||
select USB_F_SUBSET
|
||||
help
|
||||
Include a configuration with CDC ECM function (Ethernet) and the
|
||||
Function Filesystem.
|
||||
|
||||
config USB_FUNCTIONFS_RNDIS
|
||||
bool "Include configuration with RNDIS (Ethernet)"
|
||||
depends on USB_FUNCTIONFS && NET
|
||||
select USB_U_ETHER
|
||||
select USB_F_RNDIS
|
||||
help
|
||||
Include a configuration with RNDIS function (Ethernet) and the Filesystem.
|
||||
|
||||
config USB_FUNCTIONFS_GENERIC
|
||||
bool "Include 'pure' configuration"
|
||||
depends on USB_FUNCTIONFS
|
||||
help
|
||||
Include a configuration with the Function Filesystem alone with
|
||||
no Ethernet interface.
|
||||
|
||||
config USB_MASS_STORAGE
|
||||
tristate "Mass Storage Gadget"
|
||||
depends on BLOCK
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_F_MASS_STORAGE
|
||||
help
|
||||
The Mass Storage Gadget acts as a USB Mass Storage disk drive.
|
||||
As its storage repository it can use a regular file or a block
|
||||
device (in much the same way as the "loop" device driver),
|
||||
specified as a module parameter or sysfs option.
|
||||
|
||||
This driver is a replacement for now removed File-backed
|
||||
Storage Gadget (g_file_storage).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build
|
||||
a dynamically linked module called "g_mass_storage".
|
||||
|
||||
config USB_GADGET_TARGET
|
||||
tristate "USB Gadget Target Fabric Module"
|
||||
depends on TARGET_CORE
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
This fabric is an USB gadget. Two USB protocols are supported that is
|
||||
BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
|
||||
advertised on alternative interface 0 (primary) and UAS is on
|
||||
alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
|
||||
UAS utilizes the USB 3.0 feature called streams support.
|
||||
|
||||
config USB_G_SERIAL
|
||||
tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
|
||||
depends on TTY
|
||||
select USB_U_SERIAL
|
||||
select USB_F_ACM
|
||||
select USB_F_SERIAL
|
||||
select USB_F_OBEX
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Serial Gadget talks to the Linux-USB generic serial driver.
|
||||
This driver supports a CDC-ACM module option, which can be used
|
||||
to interoperate with MS-Windows hosts or with the Linux-USB
|
||||
"cdc-acm" driver.
|
||||
|
||||
This driver also supports a CDC-OBEX option. You will need a
|
||||
user space OBEX server talking to /dev/ttyGS*, since the kernel
|
||||
itself doesn't implement the OBEX protocol.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_serial".
|
||||
|
||||
For more information, see Documentation/usb/gadget_serial.txt
|
||||
which includes instructions and a "driver info file" needed to
|
||||
make MS-Windows work with CDC ACM.
|
||||
|
||||
config USB_MIDI_GADGET
|
||||
tristate "MIDI Gadget"
|
||||
depends on SND
|
||||
select USB_LIBCOMPOSITE
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
The MIDI Gadget acts as a USB Audio device, with one MIDI
|
||||
input and one MIDI output. These MIDI jacks appear as
|
||||
a sound "card" in the ALSA sound system. Other MIDI
|
||||
connections can then be made on the gadget system, using
|
||||
ALSA's aconnect utility etc.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_midi".
|
||||
|
||||
config USB_G_PRINTER
|
||||
tristate "Printer Gadget"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Printer Gadget channels data between the USB host and a
|
||||
userspace program driving the print engine. The user space
|
||||
program reads and writes the device file /dev/g_printer to
|
||||
receive or send printer data. It can use ioctl calls to
|
||||
the device file to get or set printer status.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_printer".
|
||||
|
||||
For more information, see Documentation/usb/gadget_printer.txt
|
||||
which includes sample code for accessing the device file.
|
||||
|
||||
if TTY
|
||||
|
||||
config USB_CDC_COMPOSITE
|
||||
tristate "CDC Composite Device (Ethernet and ACM)"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_SERIAL
|
||||
select USB_U_ETHER
|
||||
select USB_F_ACM
|
||||
select USB_F_ECM
|
||||
help
|
||||
This driver provides two functions in one configuration:
|
||||
a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
|
||||
|
||||
This driver requires four bulk and two interrupt endpoints,
|
||||
plus the ability to handle altsettings. Not all peripheral
|
||||
controllers are that capable.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module.
|
||||
|
||||
config USB_G_NOKIA
|
||||
tristate "Nokia composite gadget"
|
||||
depends on PHONET
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_SERIAL
|
||||
select USB_U_ETHER
|
||||
select USB_F_ACM
|
||||
select USB_F_OBEX
|
||||
select USB_F_PHONET
|
||||
select USB_F_ECM
|
||||
help
|
||||
The Nokia composite gadget provides support for acm, obex
|
||||
and phonet in only one composite gadget driver.
|
||||
|
||||
It's only really useful for N900 hardware. If you're building
|
||||
a kernel for N900, say Y or M here. If unsure, say N.
|
||||
|
||||
config USB_G_ACM_MS
|
||||
tristate "CDC Composite Device (ACM and mass storage)"
|
||||
depends on BLOCK
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_SERIAL
|
||||
select USB_F_ACM
|
||||
select USB_F_MASS_STORAGE
|
||||
help
|
||||
This driver provides two functions in one configuration:
|
||||
a mass storage, and a CDC ACM (serial port) link.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_acm_ms".
|
||||
|
||||
config USB_G_MULTI
|
||||
tristate "Multifunction Composite Gadget"
|
||||
depends on BLOCK && NET
|
||||
select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_U_SERIAL
|
||||
select USB_U_ETHER
|
||||
select USB_F_ACM
|
||||
select USB_F_MASS_STORAGE
|
||||
help
|
||||
The Multifunction Composite Gadget provides Ethernet (RNDIS
|
||||
and/or CDC Ethernet), mass storage and ACM serial link
|
||||
interfaces.
|
||||
|
||||
You will be asked to choose which of the two configurations is
|
||||
to be available in the gadget. At least one configuration must
|
||||
be chosen to make the gadget usable. Selecting more than one
|
||||
configuration will prevent Windows from automatically detecting
|
||||
the gadget as a composite gadget, so an INF file will be needed to
|
||||
use the gadget.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_multi".
|
||||
|
||||
config USB_G_MULTI_RNDIS
|
||||
bool "RNDIS + CDC Serial + Storage configuration"
|
||||
depends on USB_G_MULTI
|
||||
select USB_F_RNDIS
|
||||
default y
|
||||
help
|
||||
This option enables a configuration with RNDIS, CDC Serial and
|
||||
Mass Storage functions available in the Multifunction Composite
|
||||
Gadget. This is the configuration dedicated for Windows since RNDIS
|
||||
is Microsoft's protocol.
|
||||
|
||||
If unsure, say "y".
|
||||
|
||||
config USB_G_MULTI_CDC
|
||||
bool "CDC Ethernet + CDC Serial + Storage configuration"
|
||||
depends on USB_G_MULTI
|
||||
default n
|
||||
select USB_F_ECM
|
||||
help
|
||||
This option enables a configuration with CDC Ethernet (ECM), CDC
|
||||
Serial and Mass Storage functions available in the Multifunction
|
||||
Composite Gadget.
|
||||
|
||||
If unsure, say "y".
|
||||
|
||||
endif # TTY
|
||||
|
||||
config USB_G_HID
|
||||
tristate "HID Gadget"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The HID gadget driver provides generic emulation of USB
|
||||
Human Interface Devices (HID).
|
||||
|
||||
For more information, see Documentation/usb/gadget_hid.txt which
|
||||
includes sample code for accessing the device files.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_hid".
|
||||
|
||||
# Standalone / single function gadgets
|
||||
config USB_G_DBGP
|
||||
tristate "EHCI Debug Device Gadget"
|
||||
depends on TTY
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
This gadget emulates an EHCI Debug device. This is useful when you want
|
||||
to interact with an EHCI Debug Port.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_dbgp".
|
||||
|
||||
if USB_G_DBGP
|
||||
choice
|
||||
prompt "EHCI Debug Device mode"
|
||||
default USB_G_DBGP_SERIAL
|
||||
|
||||
config USB_G_DBGP_PRINTK
|
||||
depends on USB_G_DBGP
|
||||
bool "printk"
|
||||
help
|
||||
Directly printk() received data. No interaction.
|
||||
|
||||
config USB_G_DBGP_SERIAL
|
||||
depends on USB_G_DBGP
|
||||
select USB_U_SERIAL
|
||||
bool "serial"
|
||||
help
|
||||
Userland can interact using /dev/ttyGSxxx.
|
||||
endchoice
|
||||
endif
|
||||
|
||||
# put drivers that need isochronous transfer support (for audio
|
||||
# or video class gadget drivers), or specific hardware, here.
|
||||
config USB_G_WEBCAM
|
||||
tristate "USB Webcam Gadget"
|
||||
depends on VIDEO_DEV
|
||||
select USB_LIBCOMPOSITE
|
||||
select VIDEOBUF2_VMALLOC
|
||||
help
|
||||
The Webcam Gadget acts as a composite USB Audio and Video Class
|
||||
device. It provides a userspace API to process UVC control requests
|
||||
and stream video data to the host.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_webcam".
|
|
@ -0,0 +1,44 @@
|
|||
#
|
||||
# USB gadget drivers
|
||||
#
|
||||
|
||||
ccflags-y := -I$(PWD)/drivers/usb/gadget/
|
||||
ccflags-y += -I$(PWD)/drivers/usb/gadget/udc/
|
||||
ccflags-y += -I$(PWD)/drivers/usb/gadget/function/
|
||||
|
||||
g_zero-y := zero.o
|
||||
g_audio-y := audio.o
|
||||
g_ether-y := ether.o
|
||||
g_serial-y := serial.o
|
||||
g_midi-y := gmidi.o
|
||||
gadgetfs-y := inode.o
|
||||
g_mass_storage-y := mass_storage.o
|
||||
g_printer-y := printer.o
|
||||
g_cdc-y := cdc2.o
|
||||
g_multi-y := multi.o
|
||||
g_hid-y := hid.o
|
||||
g_dbgp-y := dbgp.o
|
||||
g_nokia-y := nokia.o
|
||||
g_webcam-y := webcam.o
|
||||
g_ncm-y := ncm.o
|
||||
g_acm_ms-y := acm_ms.o
|
||||
g_tcm_usb_gadget-y := tcm_usb_gadget.o
|
||||
|
||||
obj-$(CONFIG_USB_ZERO) += g_zero.o
|
||||
obj-$(CONFIG_USB_AUDIO) += g_audio.o
|
||||
obj-$(CONFIG_USB_ETH) += g_ether.o
|
||||
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
|
||||
obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
|
||||
obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
|
||||
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
|
||||
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
|
||||
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
|
||||
obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
|
||||
obj-$(CONFIG_USB_G_HID) += g_hid.o
|
||||
obj-$(CONFIG_USB_G_DBGP) += g_dbgp.o
|
||||
obj-$(CONFIG_USB_G_MULTI) += g_multi.o
|
||||
obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
|
||||
obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
|
||||
obj-$(CONFIG_USB_G_NCM) += g_ncm.o
|
||||
obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
|
||||
obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
|
|
@ -267,18 +267,8 @@ static __refdata struct usb_composite_driver acm_ms_driver = {
|
|||
.unbind = __exit_p(acm_ms_unbind),
|
||||
};
|
||||
|
||||
module_usb_composite_driver(acm_ms_driver);
|
||||
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_AUTHOR("Klaus Schwarzkopf <schwarzkopf@sensortherm.de>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&acm_ms_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
static void __exit cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(&acm_ms_driver);
|
||||
}
|
||||
module_exit(cleanup);
|
|
@ -172,17 +172,7 @@ static __refdata struct usb_composite_driver audio_driver = {
|
|||
.unbind = __exit_p(audio_unbind),
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&audio_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
static void __exit cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(&audio_driver);
|
||||
}
|
||||
module_exit(cleanup);
|
||||
module_usb_composite_driver(audio_driver);
|
||||
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_AUTHOR("Bryan Wu <cooloney@kernel.org>");
|
|
@ -231,18 +231,8 @@ static __refdata struct usb_composite_driver cdc_driver = {
|
|||
.unbind = __exit_p(cdc_unbind),
|
||||
};
|
||||
|
||||
module_usb_composite_driver(cdc_driver);
|
||||
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&cdc_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
static void __exit cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(&cdc_driver);
|
||||
}
|
||||
module_exit(cleanup);
|
|
@ -475,18 +475,8 @@ static __refdata struct usb_composite_driver eth_driver = {
|
|||
.unbind = __exit_p(eth_unbind),
|
||||
};
|
||||
|
||||
module_usb_composite_driver(eth_driver);
|
||||
|
||||
MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
|
||||
MODULE_AUTHOR("David Brownell, Benedikt Spanger");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(ð_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
static void __exit cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(ð_driver);
|
||||
}
|
||||
module_exit(cleanup);
|
|
@ -276,7 +276,7 @@ module_exit(gfs_exit);
|
|||
static void *functionfs_acquire_dev(struct ffs_dev *dev)
|
||||
{
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return ERR_PTR(-ENODEV);
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -163,15 +163,4 @@ static __refdata struct usb_composite_driver midi_driver = {
|
|||
.unbind = __exit_p(midi_unbind),
|
||||
};
|
||||
|
||||
static int __init midi_init(void)
|
||||
{
|
||||
return usb_composite_probe(&midi_driver);
|
||||
}
|
||||
module_init(midi_init);
|
||||
|
||||
static void __exit midi_cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(&midi_driver);
|
||||
}
|
||||
module_exit(midi_cleanup);
|
||||
|
||||
module_usb_composite_driver(midi_driver);
|
|
@ -507,15 +507,4 @@ static __refdata struct usb_composite_driver multi_driver = {
|
|||
.needs_serial = 1,
|
||||
};
|
||||
|
||||
|
||||
static int __init multi_init(void)
|
||||
{
|
||||
return usb_composite_probe(&multi_driver);
|
||||
}
|
||||
module_init(multi_init);
|
||||
|
||||
static void __exit multi_exit(void)
|
||||
{
|
||||
usb_composite_unregister(&multi_driver);
|
||||
}
|
||||
module_exit(multi_exit);
|
||||
module_usb_composite_driver(multi_driver);
|
|
@ -204,18 +204,8 @@ static __refdata struct usb_composite_driver ncm_driver = {
|
|||
.unbind = __exit_p(gncm_unbind),
|
||||
};
|
||||
|
||||
module_usb_composite_driver(ncm_driver);
|
||||
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_AUTHOR("Yauheni Kaliuta");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&ncm_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
static void __exit cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(&ncm_driver);
|
||||
}
|
||||
module_exit(cleanup);
|
|
@ -347,14 +347,4 @@ static __refdata struct usb_composite_driver nokia_driver = {
|
|||
.unbind = __exit_p(nokia_unbind),
|
||||
};
|
||||
|
||||
static int __init nokia_init(void)
|
||||
{
|
||||
return usb_composite_probe(&nokia_driver);
|
||||
}
|
||||
module_init(nokia_init);
|
||||
|
||||
static void __exit nokia_cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(&nokia_driver);
|
||||
}
|
||||
module_exit(nokia_cleanup);
|
||||
module_usb_composite_driver(nokia_driver);
|
|
@ -390,20 +390,7 @@ static __refdata struct usb_composite_driver webcam_driver = {
|
|||
.unbind = webcam_unbind,
|
||||
};
|
||||
|
||||
static int __init
|
||||
webcam_init(void)
|
||||
{
|
||||
return usb_composite_probe(&webcam_driver);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
webcam_cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(&webcam_driver);
|
||||
}
|
||||
|
||||
module_init(webcam_init);
|
||||
module_exit(webcam_cleanup);
|
||||
module_usb_composite_driver(webcam_driver);
|
||||
|
||||
MODULE_AUTHOR("Laurent Pinchart");
|
||||
MODULE_DESCRIPTION("Webcam Video Gadget");
|
|
@ -411,17 +411,7 @@ static __refdata struct usb_composite_driver zero_driver = {
|
|||
.resume = zero_resume,
|
||||
};
|
||||
|
||||
module_usb_composite_driver(zero_driver);
|
||||
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&zero_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
static void __exit cleanup(void)
|
||||
{
|
||||
usb_composite_unregister(&zero_driver);
|
||||
}
|
||||
module_exit(cleanup);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,308 +0,0 @@
|
|||
/*
|
||||
* NetChip 2280 high/full speed USB device controller.
|
||||
* Unlike many such controllers, this one talks PCI.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
|
||||
* Copyright (C) 2003 David Brownell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/usb/net2280.h>
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* indexed registers [11.10] are accessed indirectly
|
||||
* caller must own the device lock.
|
||||
*/
|
||||
|
||||
static inline u32
|
||||
get_idx_reg (struct net2280_regs __iomem *regs, u32 index)
|
||||
{
|
||||
writel (index, ®s->idxaddr);
|
||||
/* NOTE: synchs device/cpu memory views */
|
||||
return readl (®s->idxdata);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_idx_reg (struct net2280_regs __iomem *regs, u32 index, u32 value)
|
||||
{
|
||||
writel (index, ®s->idxaddr);
|
||||
writel (value, ®s->idxdata);
|
||||
/* posted, may not be visible yet */
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
||||
#define REG_DIAG 0x0
|
||||
#define RETRY_COUNTER 16
|
||||
#define FORCE_PCI_SERR 11
|
||||
#define FORCE_PCI_INTERRUPT 10
|
||||
#define FORCE_USB_INTERRUPT 9
|
||||
#define FORCE_CPU_INTERRUPT 8
|
||||
#define ILLEGAL_BYTE_ENABLES 5
|
||||
#define FAST_TIMES 4
|
||||
#define FORCE_RECEIVE_ERROR 2
|
||||
#define FORCE_TRANSMIT_CRC_ERROR 0
|
||||
#define REG_FRAME 0x02 /* from last sof */
|
||||
#define REG_CHIPREV 0x03 /* in bcd */
|
||||
#define REG_HS_NAK_RATE 0x0a /* NAK per N uframes */
|
||||
|
||||
#define CHIPREV_1 0x0100
|
||||
#define CHIPREV_1A 0x0110
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* ep a-f highspeed and fullspeed maxpacket, addresses
|
||||
* computed from ep->num
|
||||
*/
|
||||
#define REG_EP_MAXPKT(dev,num) (((num) + 1) * 0x10 + \
|
||||
(((dev)->gadget.speed == USB_SPEED_HIGH) ? 0 : 1))
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* [8.3] for scatter/gather i/o
|
||||
* use struct net2280_dma_regs bitfields
|
||||
*/
|
||||
struct net2280_dma {
|
||||
__le32 dmacount;
|
||||
__le32 dmaaddr; /* the buffer */
|
||||
__le32 dmadesc; /* next dma descriptor */
|
||||
__le32 _reserved;
|
||||
} __attribute__ ((aligned (16)));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* DRIVER DATA STRUCTURES and UTILITIES */
|
||||
|
||||
struct net2280_ep {
|
||||
struct usb_ep ep;
|
||||
struct net2280_ep_regs __iomem *regs;
|
||||
struct net2280_dma_regs __iomem *dma;
|
||||
struct net2280_dma *dummy;
|
||||
dma_addr_t td_dma; /* of dummy */
|
||||
struct net2280 *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,
|
||||
in_fifo_validate : 1,
|
||||
out_overflow : 1,
|
||||
stopped : 1,
|
||||
wedged : 1,
|
||||
is_in : 1,
|
||||
is_iso : 1,
|
||||
responded : 1;
|
||||
};
|
||||
|
||||
static inline void allow_status (struct net2280_ep *ep)
|
||||
{
|
||||
/* ep0 only */
|
||||
writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
|
||||
| (1 << CLEAR_NAK_OUT_PACKETS)
|
||||
| (1 << CLEAR_NAK_OUT_PACKETS_MODE)
|
||||
, &ep->regs->ep_rsp);
|
||||
ep->stopped = 1;
|
||||
}
|
||||
|
||||
/* count (<= 4) bytes in the next fifo write will be valid */
|
||||
static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
|
||||
{
|
||||
writeb (count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
|
||||
}
|
||||
|
||||
struct net2280_request {
|
||||
struct usb_request req;
|
||||
struct net2280_dma *td;
|
||||
dma_addr_t td_dma;
|
||||
struct list_head queue;
|
||||
unsigned mapped : 1,
|
||||
valid : 1;
|
||||
};
|
||||
|
||||
struct net2280 {
|
||||
/* each pci device provides one gadget, several endpoints */
|
||||
struct usb_gadget gadget;
|
||||
spinlock_t lock;
|
||||
struct net2280_ep ep [7];
|
||||
struct usb_gadget_driver *driver;
|
||||
unsigned enabled : 1,
|
||||
protocol_stall : 1,
|
||||
softconnect : 1,
|
||||
got_irq : 1,
|
||||
region : 1;
|
||||
u16 chiprev;
|
||||
|
||||
/* pci state used to access those endpoints */
|
||||
struct pci_dev *pdev;
|
||||
struct net2280_regs __iomem *regs;
|
||||
struct net2280_usb_regs __iomem *usb;
|
||||
struct net2280_pci_regs __iomem *pci;
|
||||
struct net2280_dma_regs __iomem *dma;
|
||||
struct net2280_dep_regs __iomem *dep;
|
||||
struct net2280_ep_regs __iomem *epregs;
|
||||
|
||||
struct pci_pool *requests;
|
||||
// statistics...
|
||||
};
|
||||
|
||||
static inline void set_halt (struct net2280_ep *ep)
|
||||
{
|
||||
/* ep0 and bulk/intr endpoints */
|
||||
writel ( (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
|
||||
/* set NAK_OUT for erratum 0114 */
|
||||
| ((ep->dev->chiprev == CHIPREV_1) << SET_NAK_OUT_PACKETS)
|
||||
| (1 << SET_ENDPOINT_HALT)
|
||||
, &ep->regs->ep_rsp);
|
||||
}
|
||||
|
||||
static inline void clear_halt (struct net2280_ep *ep)
|
||||
{
|
||||
/* ep0 and bulk/intr endpoints */
|
||||
writel ( (1 << CLEAR_ENDPOINT_HALT)
|
||||
| (1 << CLEAR_ENDPOINT_TOGGLE)
|
||||
/* unless the gadget driver left a short packet in the
|
||||
* fifo, this reverses the erratum 0114 workaround.
|
||||
*/
|
||||
| ((ep->dev->chiprev == CHIPREV_1) << CLEAR_NAK_OUT_PACKETS)
|
||||
, &ep->regs->ep_rsp);
|
||||
}
|
||||
|
||||
#ifdef USE_RDK_LEDS
|
||||
|
||||
static inline void net2280_led_init (struct net2280 *dev)
|
||||
{
|
||||
/* LED3 (green) is on during USB activity. note erratum 0113. */
|
||||
writel ((1 << GPIO3_LED_SELECT)
|
||||
| (1 << GPIO3_OUTPUT_ENABLE)
|
||||
| (1 << GPIO2_OUTPUT_ENABLE)
|
||||
| (1 << GPIO1_OUTPUT_ENABLE)
|
||||
| (1 << GPIO0_OUTPUT_ENABLE)
|
||||
, &dev->regs->gpioctl);
|
||||
}
|
||||
|
||||
/* indicate speed with bi-color LED 0/1 */
|
||||
static inline
|
||||
void net2280_led_speed (struct net2280 *dev, enum usb_device_speed speed)
|
||||
{
|
||||
u32 val = readl (&dev->regs->gpioctl);
|
||||
switch (speed) {
|
||||
case USB_SPEED_HIGH: /* green */
|
||||
val &= ~(1 << GPIO0_DATA);
|
||||
val |= (1 << GPIO1_DATA);
|
||||
break;
|
||||
case USB_SPEED_FULL: /* red */
|
||||
val &= ~(1 << GPIO1_DATA);
|
||||
val |= (1 << GPIO0_DATA);
|
||||
break;
|
||||
default: /* (off/black) */
|
||||
val &= ~((1 << GPIO1_DATA) | (1 << GPIO0_DATA));
|
||||
break;
|
||||
}
|
||||
writel (val, &dev->regs->gpioctl);
|
||||
}
|
||||
|
||||
/* indicate power with LED 2 */
|
||||
static inline void net2280_led_active (struct net2280 *dev, int is_active)
|
||||
{
|
||||
u32 val = readl (&dev->regs->gpioctl);
|
||||
|
||||
// FIXME this LED never seems to turn on.
|
||||
if (is_active)
|
||||
val |= GPIO2_DATA;
|
||||
else
|
||||
val &= ~GPIO2_DATA;
|
||||
writel (val, &dev->regs->gpioctl);
|
||||
}
|
||||
static inline void net2280_led_shutdown (struct net2280 *dev)
|
||||
{
|
||||
/* turn off all four GPIO*_DATA bits */
|
||||
writel (readl (&dev->regs->gpioctl) & ~0x0f,
|
||||
&dev->regs->gpioctl);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define net2280_led_init(dev) do { } while (0)
|
||||
#define net2280_led_speed(dev, speed) do { } while (0)
|
||||
#define net2280_led_shutdown(dev) do { } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define xprintk(dev,level,fmt,args...) \
|
||||
printk(level "%s %s: " fmt , driver_name , \
|
||||
pci_name(dev->pdev) , ## args)
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef DEBUG
|
||||
#define DEBUG(dev,fmt,args...) \
|
||||
xprintk(dev , KERN_DEBUG , fmt , ## args)
|
||||
#else
|
||||
#define DEBUG(dev,fmt,args...) \
|
||||
do { } while (0)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef VERBOSE
|
||||
#define VDEBUG DEBUG
|
||||
#else
|
||||
#define VDEBUG(dev,fmt,args...) \
|
||||
do { } while (0)
|
||||
#endif /* VERBOSE */
|
||||
|
||||
#define ERROR(dev,fmt,args...) \
|
||||
xprintk(dev , KERN_ERR , fmt , ## args)
|
||||
#define WARNING(dev,fmt,args...) \
|
||||
xprintk(dev , KERN_WARNING , fmt , ## args)
|
||||
#define INFO(dev,fmt,args...) \
|
||||
xprintk(dev , KERN_INFO , fmt , ## args)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static inline void start_out_naking (struct net2280_ep *ep)
|
||||
{
|
||||
/* NOTE: hardware races lurk here, and PING protocol issues */
|
||||
writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
|
||||
/* synch with device */
|
||||
readl (&ep->regs->ep_rsp);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline void assert_out_naking (struct net2280_ep *ep, const char *where)
|
||||
{
|
||||
u32 tmp = readl (&ep->regs->ep_stat);
|
||||
|
||||
if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) {
|
||||
DEBUG (ep->dev, "%s %s %08x !NAK\n",
|
||||
ep->ep.name, where, tmp);
|
||||
writel ((1 << SET_NAK_OUT_PACKETS),
|
||||
&ep->regs->ep_rsp);
|
||||
}
|
||||
}
|
||||
#define ASSERT_OUT_NAKING(ep) assert_out_naking(ep,__func__)
|
||||
#else
|
||||
#define ASSERT_OUT_NAKING(ep) do {} while (0)
|
||||
#endif
|
||||
|
||||
static inline void stop_out_naking (struct net2280_ep *ep)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl (&ep->regs->ep_stat);
|
||||
if ((tmp & (1 << NAK_OUT_PACKETS)) != 0)
|
||||
writel ((1 << CLEAR_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
|
@ -35,27 +35,63 @@
|
|||
#define USB_EXT_PROP_UNICODE_LINK 6
|
||||
#define USB_EXT_PROP_UNICODE_MULTI 7
|
||||
|
||||
static inline u8 *__usb_ext_prop_ptr(u8 *buf, size_t offset)
|
||||
{
|
||||
return buf + offset;
|
||||
}
|
||||
|
||||
static inline u8 *usb_ext_prop_size_ptr(u8 *buf)
|
||||
{
|
||||
return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_SIZE);
|
||||
}
|
||||
|
||||
static inline u8 *usb_ext_prop_type_ptr(u8 *buf)
|
||||
{
|
||||
return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_PROPERTY_DATA_TYPE);
|
||||
}
|
||||
|
||||
static inline u8 *usb_ext_prop_name_len_ptr(u8 *buf)
|
||||
{
|
||||
return __usb_ext_prop_ptr(buf, USB_EXT_PROP_W_PROPERTY_NAME_LENGTH);
|
||||
}
|
||||
|
||||
static inline u8 *usb_ext_prop_name_ptr(u8 *buf)
|
||||
{
|
||||
return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
static inline u8 *usb_ext_prop_data_len_ptr(u8 *buf, size_t off)
|
||||
{
|
||||
return __usb_ext_prop_ptr(buf,
|
||||
USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + off);
|
||||
}
|
||||
|
||||
static inline u8 *usb_ext_prop_data_ptr(u8 *buf, size_t off)
|
||||
{
|
||||
return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_DATA + off);
|
||||
}
|
||||
|
||||
static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
|
||||
{
|
||||
put_unaligned_le32(dw_size, &buf[USB_EXT_PROP_DW_SIZE]);
|
||||
put_unaligned_le32(dw_size, usb_ext_prop_size_ptr(buf));
|
||||
}
|
||||
|
||||
static inline void usb_ext_prop_put_type(u8 *buf, int type)
|
||||
{
|
||||
put_unaligned_le32(type, &buf[USB_EXT_PROP_DW_PROPERTY_DATA_TYPE]);
|
||||
put_unaligned_le32(type, usb_ext_prop_type_ptr(buf));
|
||||
}
|
||||
|
||||
static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
|
||||
{
|
||||
int result;
|
||||
|
||||
put_unaligned_le16(pnl, &buf[USB_EXT_PROP_W_PROPERTY_NAME_LENGTH]);
|
||||
put_unaligned_le16(pnl, usb_ext_prop_name_len_ptr(buf));
|
||||
result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN,
|
||||
(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_NAME], pnl - 2);
|
||||
(wchar_t *) usb_ext_prop_name_ptr(buf), pnl - 2);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl]);
|
||||
put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl - 2]);
|
||||
|
||||
return pnl;
|
||||
}
|
||||
|
@ -63,26 +99,23 @@ static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
|
|||
static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
|
||||
int data_len)
|
||||
{
|
||||
put_unaligned_le32(data_len,
|
||||
&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
|
||||
memcpy(&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl], data, data_len);
|
||||
put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
|
||||
memcpy(usb_ext_prop_data_ptr(buf, pnl), data, data_len);
|
||||
}
|
||||
|
||||
static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
|
||||
int data_len)
|
||||
{
|
||||
int result;
|
||||
put_unaligned_le32(data_len,
|
||||
&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
|
||||
|
||||
put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
|
||||
result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
|
||||
(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl],
|
||||
(wchar_t *) usb_ext_prop_data_ptr(buf, pnl),
|
||||
data_len - 2);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
put_unaligned_le16(0,
|
||||
&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len]);
|
||||
&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len - 2]);
|
||||
|
||||
return data_len;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,385 @@
|
|||
#
|
||||
# USB Gadget support on a system involves
|
||||
# (a) a peripheral controller, and
|
||||
# (b) the gadget driver using it.
|
||||
#
|
||||
# NOTE: Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
|
||||
#
|
||||
# - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
|
||||
# - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
|
||||
# - Some systems have both kinds of controllers.
|
||||
#
|
||||
# With help from a special transceiver and a "Mini-AB" jack, systems with
|
||||
# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
|
||||
#
|
||||
|
||||
#
|
||||
# USB Peripheral Controller Support
|
||||
#
|
||||
# The order here is alphabetical, except that integrated controllers go
|
||||
# before discrete ones so they will be the initial/default value:
|
||||
# - integrated/SOC controllers first
|
||||
# - licensed IP used in both SOC and discrete versions
|
||||
# - discrete ones (including all PCI-only controllers)
|
||||
# - debug/dummy gadget+hcd is last.
|
||||
#
|
||||
menu "USB Peripheral Controller"
|
||||
|
||||
#
|
||||
# Integrated controllers
|
||||
#
|
||||
|
||||
config USB_AT91
|
||||
tristate "Atmel AT91 USB Device Port"
|
||||
depends on ARCH_AT91
|
||||
help
|
||||
Many Atmel AT91 processors (such as the AT91RM2000) have a
|
||||
full speed USB Device Port with support for five configurable
|
||||
endpoints (plus endpoint zero).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "at91_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_LPC32XX
|
||||
tristate "LPC32XX USB Peripheral Controller"
|
||||
depends on ARCH_LPC32XX && I2C
|
||||
select USB_ISP1301
|
||||
help
|
||||
This option selects the USB device controller in the LPC32xx SoC.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "lpc32xx_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_ATMEL_USBA
|
||||
tristate "Atmel USBA"
|
||||
depends on AVR32 || ARCH_AT91
|
||||
help
|
||||
USBA is the integrated high-speed USB Device controller on
|
||||
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
|
||||
|
||||
config USB_BCM63XX_UDC
|
||||
tristate "Broadcom BCM63xx Peripheral Controller"
|
||||
depends on BCM63XX
|
||||
help
|
||||
Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
|
||||
high speed USB Device Port with support for four fixed endpoints
|
||||
(plus endpoint zero).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "bcm63xx_udc".
|
||||
|
||||
config USB_FSL_USB2
|
||||
tristate "Freescale Highspeed USB DR Peripheral Controller"
|
||||
depends on FSL_SOC || ARCH_MXC
|
||||
select USB_FSL_MPH_DR_OF if OF
|
||||
help
|
||||
Some of Freescale PowerPC and i.MX processors have a High Speed
|
||||
Dual-Role(DR) USB controller, which supports device mode.
|
||||
|
||||
The number of programmable endpoints is different through
|
||||
SOC revisions.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "fsl_usb2_udc" and force
|
||||
all gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_FUSB300
|
||||
tristate "Faraday FUSB300 USB Peripheral Controller"
|
||||
depends on !PHYS_ADDR_T_64BIT && HAS_DMA
|
||||
help
|
||||
Faraday usb device controller FUSB300 driver
|
||||
|
||||
config USB_FOTG210_UDC
|
||||
depends on HAS_DMA
|
||||
tristate "Faraday FOTG210 USB Peripheral Controller"
|
||||
help
|
||||
Faraday USB2.0 OTG controller which can be configured as
|
||||
high speed or full speed USB device. This driver supppors
|
||||
Bulk Transfer so far.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "fotg210_udc".
|
||||
|
||||
config USB_GR_UDC
|
||||
tristate "Aeroflex Gaisler GRUSBDC USB Peripheral Controller Driver"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB
|
||||
VHDL IP core library.
|
||||
|
||||
config USB_OMAP
|
||||
tristate "OMAP USB Device Controller"
|
||||
depends on ARCH_OMAP1
|
||||
depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
|
||||
help
|
||||
Many Texas Instruments OMAP processors have flexible full
|
||||
speed USB device controllers, with support for up to 30
|
||||
endpoints (plus endpoint zero). This driver supports the
|
||||
controller in the OMAP 1611, and should work with controllers
|
||||
in other OMAP processors too, given minor tweaks.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "omap_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_PXA25X
|
||||
tristate "PXA 25x or IXP 4xx"
|
||||
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
|
||||
help
|
||||
Intel's PXA 25x series XScale ARM-5TE processors include
|
||||
an integrated full speed USB 1.1 device controller. The
|
||||
controller in the IXP 4xx series is register-compatible.
|
||||
|
||||
It has fifteen fixed-function endpoints, as well as endpoint
|
||||
zero (for control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "pxa25x_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
# 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_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_R8A66597
|
||||
tristate "Renesas R8A66597 USB Peripheral Controller"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
R8A66597 is a discrete USB host and peripheral controller chip that
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
It has nine configurable endpoints, and endpoint zero.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "r8a66597_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_RENESAS_USBHS_UDC
|
||||
tristate 'Renesas USBHS controller'
|
||||
depends on USB_RENESAS_USBHS
|
||||
help
|
||||
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 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_PXA27X
|
||||
tristate "PXA 27x"
|
||||
help
|
||||
Intel's PXA 27x series XScale ARM v5TE processors include
|
||||
an integrated full speed USB 1.1 device controller.
|
||||
|
||||
It has up to 23 endpoints, as well as endpoint zero (for
|
||||
control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "pxa27x_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_S3C2410
|
||||
tristate "S3C2410 USB Device Controller"
|
||||
depends on ARCH_S3C24XX
|
||||
help
|
||||
Samsung's S3C2410 is an ARM-4 processor with an integrated
|
||||
full speed USB 1.1 device controller. It has 4 configurable
|
||||
endpoints, as well as endpoint zero (for control transfers).
|
||||
|
||||
This driver has been tested on the S3C2410, S3C2412, and
|
||||
S3C2440 processors.
|
||||
|
||||
config USB_S3C2410_DEBUG
|
||||
boolean "S3C2410 udc debug messages"
|
||||
depends on USB_S3C2410
|
||||
|
||||
config USB_S3C_HSUDC
|
||||
tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
|
||||
depends on ARCH_S3C24XX
|
||||
help
|
||||
Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
|
||||
integrated with dual speed USB 2.0 device controller. It has
|
||||
8 endpoints, as well as endpoint zero.
|
||||
|
||||
This driver has been tested on S3C2416 and S3C2450 processors.
|
||||
|
||||
config USB_MV_UDC
|
||||
tristate "Marvell USB2.0 Device Controller"
|
||||
depends on HAS_DMA
|
||||
help
|
||||
Marvell Socs (including PXA and MMP series) include a high speed
|
||||
USB2.0 OTG controller, which can be configured as high speed or
|
||||
full speed USB peripheral.
|
||||
|
||||
config USB_MV_U3D
|
||||
depends on HAS_DMA
|
||||
tristate "MARVELL PXA2128 USB 3.0 controller"
|
||||
help
|
||||
MARVELL PXA2128 Processor series include a super speed USB3.0 device
|
||||
controller, which support super speed USB peripheral.
|
||||
|
||||
#
|
||||
# Controllers available in both integrated and discrete versions
|
||||
#
|
||||
|
||||
config USB_M66592
|
||||
tristate "Renesas M66592 USB Peripheral Controller"
|
||||
help
|
||||
M66592 is a discrete USB peripheral controller chip that
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
It has seven configurable endpoints, and endpoint zero.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "m66592_udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
#
|
||||
# Controllers available only in discrete form (and all PCI controllers)
|
||||
#
|
||||
|
||||
config USB_AMD5536UDC
|
||||
tristate "AMD5536 UDC"
|
||||
depends on PCI
|
||||
help
|
||||
The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
|
||||
It is a USB Highspeed DMA capable USB device controller. Beside ep0
|
||||
it provides 4 IN and 4 OUT endpoints (bulk or interrupt type).
|
||||
The UDC port supports OTG operation, and may be used as a host port
|
||||
if it's not being used to implement peripheral or OTG roles.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "amd5536udc" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
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
|
||||
QE/CPM2 USB controller, which support device mode with 4
|
||||
programmable endpoints. This driver supports the
|
||||
controller in the MPC8360 and MPC8272, and should work with
|
||||
controllers having QE or CPM2, given minor tweaks.
|
||||
|
||||
Set CONFIG_USB_GADGET to "m" to build this driver as a
|
||||
dynamically linked module called "fsl_qe_udc".
|
||||
|
||||
config USB_NET2272
|
||||
tristate "PLX NET2272"
|
||||
help
|
||||
PLX NET2272 is a USB peripheral controller which supports
|
||||
both full and high speed USB 2.0 data transfers.
|
||||
|
||||
It has three configurable endpoints, as well as endpoint zero
|
||||
(for control transfer).
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "net2272" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_NET2272_DMA
|
||||
boolean "Support external DMA controller"
|
||||
depends on USB_NET2272 && HAS_DMA
|
||||
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 / PLX USB338x"
|
||||
depends on PCI
|
||||
help
|
||||
NetChip 2280 / 2282 is a PCI based USB peripheral controller which
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
|
||||
It has six configurable endpoints, as well as endpoint zero
|
||||
(for control transfers) and several endpoints with dedicated
|
||||
functions.
|
||||
|
||||
PLX 3380 / 3382 is a PCIe based USB peripheral controller which
|
||||
supports full, high speed USB 2.0 and super speed USB 3.0
|
||||
data transfers.
|
||||
|
||||
It has eight configurable endpoints, as well as endpoint zero
|
||||
(for control transfers) and several endpoints with dedicated
|
||||
functions.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "net2280" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_GOKU
|
||||
tristate "Toshiba TC86C001 'Goku-S'"
|
||||
depends on PCI
|
||||
help
|
||||
The Toshiba TC86C001 is a PCI device which includes controllers
|
||||
for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI).
|
||||
|
||||
The device controller has three configurable (bulk or interrupt)
|
||||
endpoints, plus endpoint zero (for control transfers).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "goku_udc" and to force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
config USB_EG20T
|
||||
tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
|
||||
depends on PCI
|
||||
help
|
||||
This is a USB device driver for EG20T PCH.
|
||||
EG20T PCH is the platform controller hub that is used in Intel's
|
||||
general embedded platform. EG20T PCH has USB device interface.
|
||||
Using this interface, it is able to access system devices connected
|
||||
to USB device.
|
||||
This driver enables USB device function.
|
||||
USB device is a USB peripheral controller which
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
This driver supports both control transfer and bulk transfer modes.
|
||||
This driver dose not support interrupt transfer or isochronous
|
||||
transfer modes.
|
||||
|
||||
This driver also can be used for LAPIS Semiconductor's ML7213 which is
|
||||
for IVI(In-Vehicle Infotainment) use.
|
||||
ML7831 is for general purpose use.
|
||||
ML7213/ML7831 is companion chip for Intel Atom E6xx series.
|
||||
ML7213/ML7831 is completely compatible for Intel EG20T PCH.
|
||||
|
||||
#
|
||||
# LAST -- dummy/emulated controller
|
||||
#
|
||||
|
||||
config USB_DUMMY_HCD
|
||||
tristate "Dummy HCD (DEVELOPMENT)"
|
||||
depends on USB=y || (USB=m && USB_GADGET=m)
|
||||
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.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "dummy_hcd" and force all
|
||||
gadget drivers to also be dynamically linked.
|
||||
|
||||
# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears
|
||||
# first and will be selected by default.
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# USB peripheral controller drivers
|
||||
#
|
||||
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
|
||||
obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
|
||||
obj-$(CONFIG_USB_GOKU) += goku_udc.o
|
||||
obj-$(CONFIG_USB_OMAP) += omap_udc.o
|
||||
obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
|
||||
obj-$(CONFIG_USB_AT91) += at91_udc.o
|
||||
obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
|
||||
obj-$(CONFIG_USB_BCM63XX_UDC) += bcm63xx_udc.o
|
||||
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
|
||||
fsl_usb2_udc-y := fsl_udc_core.o
|
||||
fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
|
||||
obj-$(CONFIG_USB_M66592) += m66592-udc.o
|
||||
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
|
||||
obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
|
||||
obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o
|
||||
obj-$(CONFIG_USB_LPC32XX) += lpc32xx_udc.o
|
||||
obj-$(CONFIG_USB_EG20T) += pch_udc.o
|
||||
obj-$(CONFIG_USB_MV_UDC) += mv_udc.o
|
||||
mv_udc-y := mv_udc_core.o
|
||||
obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
|
||||
obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o
|
||||
obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
|
||||
obj-$(CONFIG_USB_GR_UDC) += gr_udc.o
|
|
@ -1979,7 +1979,7 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
|
|||
return eps;
|
||||
}
|
||||
|
||||
static int __init usba_udc_probe(struct platform_device *pdev)
|
||||
static int usba_udc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *regs, *fifo;
|
||||
struct clk *pclk, *hclk;
|
|
@ -18,6 +18,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "fsl_usb2_udc.h"
|
||||
|
||||
static struct clk *mxc_ahb_clk;
|
||||
static struct clk *mxc_per_clk;
|
||||
static struct clk *mxc_ipg_clk;
|
|
@ -2539,7 +2539,7 @@ static int qe_udc_probe(struct platform_device *ofdev)
|
|||
goto err2;
|
||||
|
||||
/* create a buf for ZLP send, need to remain zeroed */
|
||||
udc->nullbuf = kzalloc(256, GFP_KERNEL);
|
||||
udc->nullbuf = devm_kzalloc(&ofdev->dev, 256, GFP_KERNEL);
|
||||
if (udc->nullbuf == NULL) {
|
||||
dev_err(udc->dev, "cannot alloc nullbuf\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -2547,10 +2547,10 @@ static int qe_udc_probe(struct platform_device *ofdev)
|
|||
}
|
||||
|
||||
/* buffer for data of get_status request */
|
||||
udc->statusbuf = kzalloc(2, GFP_KERNEL);
|
||||
udc->statusbuf = devm_kzalloc(&ofdev->dev, 2, GFP_KERNEL);
|
||||
if (udc->statusbuf == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err4;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
udc->nullp = virt_to_phys((void *)udc->nullbuf);
|
||||
|
@ -2581,13 +2581,13 @@ static int qe_udc_probe(struct platform_device *ofdev)
|
|||
if (ret) {
|
||||
dev_err(udc->dev, "cannot request irq %d err %d\n",
|
||||
udc->usb_irq, ret);
|
||||
goto err5;
|
||||
goto err4;
|
||||
}
|
||||
|
||||
ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
|
||||
qe_udc_release);
|
||||
if (ret)
|
||||
goto err6;
|
||||
goto err5;
|
||||
|
||||
platform_set_drvdata(ofdev, udc);
|
||||
dev_info(udc->dev,
|
||||
|
@ -2595,9 +2595,9 @@ static int qe_udc_probe(struct platform_device *ofdev)
|
|||
(udc->soc_type == PORT_QE) ? "QE" : "CPM");
|
||||
return 0;
|
||||
|
||||
err6:
|
||||
free_irq(udc->usb_irq, udc);
|
||||
err5:
|
||||
free_irq(udc->usb_irq, udc);
|
||||
err4:
|
||||
irq_dispose_mapping(udc->usb_irq);
|
||||
err_noirq:
|
||||
if (udc->nullmap) {
|
||||
|
@ -2610,9 +2610,6 @@ err_noirq:
|
|||
udc->nullp, 256,
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
kfree(udc->statusbuf);
|
||||
err4:
|
||||
kfree(udc->nullbuf);
|
||||
err3:
|
||||
ep = &udc->eps[0];
|
||||
cpm_muram_free(cpm_muram_offset(ep->rxbase));
|
||||
|
@ -2660,8 +2657,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
|
|||
udc->nullp, 256,
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
kfree(udc->statusbuf);
|
||||
kfree(udc->nullbuf);
|
||||
|
||||
ep = &udc->eps[0];
|
||||
cpm_muram_free(cpm_muram_offset(ep->rxbase));
|
|
@ -59,9 +59,9 @@
|
|||
static const char driver_name[] = "fsl-usb2-udc";
|
||||
static const char driver_desc[] = DRIVER_DESC;
|
||||
|
||||
static struct usb_dr_device *dr_regs;
|
||||
static struct usb_dr_device __iomem *dr_regs;
|
||||
|
||||
static struct usb_sys_interface *usb_sys_regs;
|
||||
static struct usb_sys_interface __iomem *usb_sys_regs;
|
||||
|
||||
/* it is initialized in probe() */
|
||||
static struct fsl_udc *udc_controller = NULL;
|
||||
|
@ -159,6 +159,8 @@ static inline void fsl_set_accessors(struct fsl_usb2_platform_data *pdata) {}
|
|||
* request is still in progress.
|
||||
*--------------------------------------------------------------*/
|
||||
static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
|
||||
__releases(ep->udc->lock)
|
||||
__acquires(ep->udc->lock)
|
||||
{
|
||||
struct fsl_udc *udc = NULL;
|
||||
unsigned char stopped = ep->stopped;
|
||||
|
@ -1392,6 +1394,8 @@ stall:
|
|||
|
||||
static void setup_received_irq(struct fsl_udc *udc,
|
||||
struct usb_ctrlrequest *setup)
|
||||
__releases(udc->lock)
|
||||
__acquires(udc->lock)
|
||||
{
|
||||
u16 wValue = le16_to_cpu(setup->wValue);
|
||||
u16 wIndex = le16_to_cpu(setup->wIndex);
|
||||
|
@ -1957,8 +1961,7 @@ static int fsl_udc_start(struct usb_gadget *g,
|
|||
&udc_controller->gadget);
|
||||
if (retval < 0) {
|
||||
ERR("can't bind to transceiver\n");
|
||||
driver->unbind(&udc_controller->gadget);
|
||||
udc_controller->driver = 0;
|
||||
udc_controller->driver = NULL;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
@ -2246,7 +2249,7 @@ static void fsl_udc_release(struct device *dev)
|
|||
* init resource for globle controller
|
||||
* Return the udc handle on success or NULL on failure
|
||||
------------------------------------------------------------------*/
|
||||
static int __init struct_udc_setup(struct fsl_udc *udc,
|
||||
static int struct_udc_setup(struct fsl_udc *udc,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct fsl_usb2_platform_data *pdata;
|
||||
|
@ -2298,7 +2301,7 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
|
|||
* ep0out is not used so do nothing here
|
||||
* ep0in should be taken care
|
||||
*--------------------------------------------------------------*/
|
||||
static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
|
||||
static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
|
||||
char *name, int link)
|
||||
{
|
||||
struct fsl_ep *ep = &udc->eps[index];
|
||||
|
@ -2331,7 +2334,7 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
|
|||
* all intialization operations implemented here except enabling usb_intr reg
|
||||
* board setup should have been done in the platform code
|
||||
*/
|
||||
static int __init fsl_udc_probe(struct platform_device *pdev)
|
||||
static int fsl_udc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fsl_usb2_platform_data *pdata;
|
||||
struct resource *res;
|
||||
|
@ -2380,7 +2383,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
|
|||
goto err_release_mem_region;
|
||||
}
|
||||
|
||||
pdata->regs = (void *)dr_regs;
|
||||
pdata->regs = (void __iomem *)dr_regs;
|
||||
|
||||
/*
|
||||
* do platform specific init: check the clock, grab/config pins, etc.
|
|
@ -12,6 +12,9 @@
|
|||
#ifndef __FSL_USB2_UDC_H
|
||||
#define __FSL_USB2_UDC_H
|
||||
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
/* ### define USB registers here
|
||||
*/
|
||||
#define USB_MAX_CTRL_PAYLOAD 64
|
|
@ -1325,8 +1325,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
|
|||
{
|
||||
struct fusb300 *fusb300 = to_fusb300(g);
|
||||
|
||||
driver->unbind(&fusb300->gadget);
|
||||
|
||||
init_controller(fusb300);
|
||||
fusb300->driver = NULL;
|
||||
|
||||
|
@ -1359,7 +1357,7 @@ static int __exit fusb300_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init fusb300_probe(struct platform_device *pdev)
|
||||
static int fusb300_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res, *ires, *ires1;
|
||||
void __iomem *reg = NULL;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue