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>hifive-unleashed-5.1
commit
61fe2d75f1
|
@ -556,11 +556,11 @@ been converted to this framework.
|
||||||
Near-term plans include converting all of them, except for "gadgetfs".
|
Near-term plans include converting all of them, except for "gadgetfs".
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
!Edrivers/usb/gadget/f_acm.c
|
!Edrivers/usb/gadget/function/f_acm.c
|
||||||
!Edrivers/usb/gadget/f_ecm.c
|
!Edrivers/usb/gadget/function/f_ecm.c
|
||||||
!Edrivers/usb/gadget/f_subset.c
|
!Edrivers/usb/gadget/function/f_subset.c
|
||||||
!Edrivers/usb/gadget/f_obex.c
|
!Edrivers/usb/gadget/function/f_obex.c
|
||||||
!Edrivers/usb/gadget/f_serial.c
|
!Edrivers/usb/gadget/function/f_serial.c
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
|
@ -386,6 +386,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
||||||
}
|
}
|
||||||
dwc->revision = reg;
|
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 */
|
/* issue device SoftReset too */
|
||||||
timeout = jiffies + msecs_to_jiffies(500);
|
timeout = jiffies + msecs_to_jiffies(500);
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
|
dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST);
|
||||||
|
@ -656,6 +663,31 @@ static int dwc3_probe(struct platform_device *pdev)
|
||||||
return -ENODEV;
|
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) {
|
if (node) {
|
||||||
dwc->maximum_speed = of_usb_get_maximum_speed(node);
|
dwc->maximum_speed = of_usb_get_maximum_speed(node);
|
||||||
|
|
||||||
|
@ -676,28 +708,9 @@ static int dwc3_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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);
|
spin_lock_init(&dwc->lock);
|
||||||
platform_set_drvdata(pdev, dwc);
|
platform_set_drvdata(pdev, dwc);
|
||||||
|
|
||||||
dwc->regs = regs;
|
|
||||||
dwc->regs_size = resource_size(res);
|
|
||||||
|
|
||||||
dev->dma_mask = dev->parent->dma_mask;
|
dev->dma_mask = dev->parent->dma_mask;
|
||||||
dev->dma_parms = dev->parent->dma_parms;
|
dev->dma_parms = dev->parent->dma_parms;
|
||||||
dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
|
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(n) ((n) << 24)
|
||||||
#define DWC3_GHWPARAMS1_PWROPT_MASK DWC3_GHWPARAMS1_PWROPT(3)
|
#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 */
|
/* Global HWPARAMS4 Register */
|
||||||
#define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) & (0x0f << 13)) >> 13)
|
#define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) & (0x0f << 13)) >> 13)
|
||||||
#define DWC3_MAX_HIBER_SCRATCHBUFS 15
|
#define DWC3_MAX_HIBER_SCRATCHBUFS 15
|
||||||
|
|
|
@ -77,10 +77,6 @@
|
||||||
#define USBOTGSS_DEV_EBC_EN 0x0110
|
#define USBOTGSS_DEV_EBC_EN 0x0110
|
||||||
#define USBOTGSS_DEBUG_OFFSET 0x0600
|
#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 */
|
/* SYSCONFIG REGISTER */
|
||||||
#define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16)
|
#define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16)
|
||||||
|
|
||||||
|
@ -129,7 +125,6 @@ struct dwc3_omap {
|
||||||
u32 irq_eoi_offset;
|
u32 irq_eoi_offset;
|
||||||
u32 debug_offset;
|
u32 debug_offset;
|
||||||
u32 irq0_offset;
|
u32 irq0_offset;
|
||||||
u32 revision;
|
|
||||||
|
|
||||||
u32 dma_status:1;
|
u32 dma_status:1;
|
||||||
|
|
||||||
|
@ -383,6 +378,87 @@ static int dwc3_omap_vbus_notifier(struct notifier_block *nb,
|
||||||
return NOTIFY_DONE;
|
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)
|
static int dwc3_omap_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device_node *node = pdev->dev.of_node;
|
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 dwc3_omap *omap;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct extcon_dev *edev;
|
|
||||||
struct regulator *vbus_reg = NULL;
|
struct regulator *vbus_reg = NULL;
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
int utmi_mode = 0;
|
|
||||||
int x_major;
|
|
||||||
|
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
@ -448,58 +520,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
||||||
goto err0;
|
goto err0;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION);
|
dwc3_omap_map_offset(omap);
|
||||||
omap->revision = reg;
|
dwc3_omap_set_utmi_mode(omap);
|
||||||
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);
|
|
||||||
|
|
||||||
/* check the DMA Status */
|
/* check the DMA Status */
|
||||||
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
|
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);
|
dwc3_omap_enable_irqs(omap);
|
||||||
|
|
||||||
if (of_property_read_bool(node, "extcon")) {
|
ret = dwc3_omap_extcon_register(omap);
|
||||||
edev = extcon_get_edev_by_phandle(dev, 0);
|
if (ret < 0)
|
||||||
if (IS_ERR(edev)) {
|
goto err2;
|
||||||
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 = of_platform_populate(node, NULL, NULL, dev);
|
ret = of_platform_populate(node, NULL, NULL, dev);
|
||||||
if (ret) {
|
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,
|
static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
|
||||||
struct dwc3_ep *dep, const struct dwc3_event_depevt *event,
|
struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
|
||||||
int start_new)
|
|
||||||
{
|
{
|
||||||
unsigned status = 0;
|
unsigned status = 0;
|
||||||
int clean_busy;
|
int clean_busy;
|
||||||
|
@ -2039,7 +2038,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc3_endpoint_transfer_complete(dwc, dep, event, 1);
|
dwc3_endpoint_transfer_complete(dwc, dep, event);
|
||||||
break;
|
break;
|
||||||
case DWC3_DEPEVT_XFERINPROGRESS:
|
case DWC3_DEPEVT_XFERINPROGRESS:
|
||||||
if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
|
if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
|
||||||
|
@ -2048,7 +2047,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc3_endpoint_transfer_complete(dwc, dep, event, 0);
|
dwc3_endpoint_transfer_complete(dwc, dep, event);
|
||||||
break;
|
break;
|
||||||
case DWC3_DEPEVT_XFERNOTREADY:
|
case DWC3_DEPEVT_XFERNOTREADY:
|
||||||
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
|
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
|
||||||
|
|
|
@ -127,368 +127,7 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
|
||||||
a module parameter as well.
|
a module parameter as well.
|
||||||
If unsure, say 2.
|
If unsure, say 2.
|
||||||
|
|
||||||
#
|
source "drivers/usb/gadget/udc/Kconfig"
|
||||||
# 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
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# USB Gadget Drivers
|
# USB Gadget Drivers
|
||||||
|
@ -714,466 +353,7 @@ config USB_CONFIGFS_F_FS
|
||||||
implemented in kernel space (for instance Ethernet, serial or
|
implemented in kernel space (for instance Ethernet, serial or
|
||||||
mass storage) and other are implemented in user space.
|
mass storage) and other are implemented in user space.
|
||||||
|
|
||||||
config USB_ZERO
|
source "drivers/usb/gadget/legacy/Kconfig"
|
||||||
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".
|
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
|
|
@ -1,105 +1,12 @@
|
||||||
#
|
#
|
||||||
# USB peripheral controller drivers
|
# USB peripheral controller drivers
|
||||||
#
|
#
|
||||||
ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
|
subdir-ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
|
||||||
ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG
|
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
|
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
|
||||||
libcomposite-y := usbstring.o config.o epautoconf.o
|
libcomposite-y := usbstring.o config.o epautoconf.o
|
||||||
libcomposite-y += composite.o functions.o configfs.o u_f.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
|
obj-$(CONFIG_USB_GADGET) += udc/ function/ legacy/
|
||||||
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
|
|
||||||
|
|
|
@ -1956,6 +1956,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
|
||||||
}
|
}
|
||||||
if (cdev->req) {
|
if (cdev->req) {
|
||||||
kfree(cdev->req->buf);
|
kfree(cdev->req->buf);
|
||||||
|
usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
|
||||||
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
|
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
|
||||||
}
|
}
|
||||||
cdev->next_string_id = 0;
|
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')
|
if (page[len - 1] == '\n' || page[len - 1] == '\0')
|
||||||
--len;
|
--len;
|
||||||
new_data = kzalloc(len, GFP_KERNEL);
|
new_data = kmemdup(page, len, GFP_KERNEL);
|
||||||
if (!new_data)
|
if (!new_data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
memcpy(new_data, page, len);
|
|
||||||
|
|
||||||
if (desc->opts_mutex)
|
if (desc->opts_mutex)
|
||||||
mutex_lock(desc->opts_mutex);
|
mutex_lock(desc->opts_mutex);
|
||||||
kfree(ext_prop->data);
|
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;
|
int padlen = 0;
|
||||||
u16 len = skb->len;
|
u16 len = skb->len;
|
||||||
|
|
||||||
if (!skb_cloned(skb)) {
|
int headroom = skb_headroom(skb);
|
||||||
int headroom = skb_headroom(skb);
|
int tailroom = skb_tailroom(skb);
|
||||||
int tailroom = skb_tailroom(skb);
|
|
||||||
|
|
||||||
/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
|
/* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0,
|
||||||
* stick two bytes of zero-length EEM packet on the end.
|
* stick two bytes of zero-length EEM packet on the end.
|
||||||
*/
|
*/
|
||||||
if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
|
if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0)
|
||||||
padlen += 2;
|
padlen += 2;
|
||||||
|
|
||||||
if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
|
if ((tailroom >= (ETH_FCS_LEN + padlen)) &&
|
||||||
(headroom >= EEM_HLEN))
|
(headroom >= EEM_HLEN) && !skb_cloned(skb))
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
|
|
||||||
skb2 = skb_copy_expand(skb, EEM_HLEN, ETH_FCS_LEN + padlen, GFP_ATOMIC);
|
skb2 = skb_copy_expand(skb, EEM_HLEN, ETH_FCS_LEN + padlen, GFP_ATOMIC);
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include "u_fs.h"
|
#include "u_fs.h"
|
||||||
#include "u_f.h"
|
#include "u_f.h"
|
||||||
|
#include "u_os_desc.h"
|
||||||
#include "configfs.h"
|
#include "configfs.h"
|
||||||
|
|
||||||
#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
|
#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
|
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,
|
typedef int (*ffs_entity_callback)(enum ffs_entity_type entity,
|
||||||
u8 *valuep,
|
u8 *valuep,
|
||||||
struct usb_descriptor_header *desc,
|
struct usb_descriptor_header *desc,
|
||||||
void *priv);
|
void *priv);
|
||||||
|
|
||||||
static int __must_check ffs_do_desc(char *data, unsigned len,
|
typedef int (*ffs_os_desc_callback)(enum ffs_os_desc_type entity,
|
||||||
ffs_entity_callback entity, void *priv)
|
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;
|
struct usb_descriptor_header *_ds = (void *)data;
|
||||||
u8 length;
|
u8 length;
|
||||||
|
@ -1804,7 +1814,7 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len,
|
||||||
if (!data)
|
if (!data)
|
||||||
return _len - len;
|
return _len - len;
|
||||||
|
|
||||||
ret = ffs_do_desc(data, len, entity, priv);
|
ret = ffs_do_single_desc(data, len, entity, priv);
|
||||||
if (unlikely(ret < 0)) {
|
if (unlikely(ret < 0)) {
|
||||||
pr_debug("%s returns %d\n", __func__, ret);
|
pr_debug("%s returns %d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1857,11 +1867,191 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
|
||||||
return 0;
|
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,
|
static int __ffs_data_got_descs(struct ffs_data *ffs,
|
||||||
char *const _data, size_t len)
|
char *const _data, size_t len)
|
||||||
{
|
{
|
||||||
char *data = _data, *raw_descs;
|
char *data = _data, *raw_descs;
|
||||||
unsigned counts[3], flags;
|
unsigned os_descs_count = 0, counts[3], flags;
|
||||||
int ret = -EINVAL, i;
|
int ret = -EINVAL, i;
|
||||||
|
|
||||||
ENTER();
|
ENTER();
|
||||||
|
@ -1879,7 +2069,8 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
||||||
flags = get_unaligned_le32(data + 8);
|
flags = get_unaligned_le32(data + 8);
|
||||||
if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
|
if (flags & ~(FUNCTIONFS_HAS_FS_DESC |
|
||||||
FUNCTIONFS_HAS_HS_DESC |
|
FUNCTIONFS_HAS_HS_DESC |
|
||||||
FUNCTIONFS_HAS_SS_DESC)) {
|
FUNCTIONFS_HAS_SS_DESC |
|
||||||
|
FUNCTIONFS_HAS_MS_OS_DESC)) {
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1902,6 +2093,11 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
||||||
len -= 4;
|
len -= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (flags & (1 << i)) {
|
||||||
|
os_descs_count = get_unaligned_le32(data);
|
||||||
|
data += 4;
|
||||||
|
len -= 4;
|
||||||
|
};
|
||||||
|
|
||||||
/* Read descriptors */
|
/* Read descriptors */
|
||||||
raw_descs = data;
|
raw_descs = data;
|
||||||
|
@ -1915,6 +2111,14 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
||||||
data += ret;
|
data += ret;
|
||||||
len -= 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) {
|
if (raw_descs == data || len) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -1927,6 +2131,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
|
||||||
ffs->fs_descs_count = counts[0];
|
ffs->fs_descs_count = counts[0];
|
||||||
ffs->hs_descs_count = counts[1];
|
ffs->hs_descs_count = counts[1];
|
||||||
ffs->ss_descs_count = counts[2];
|
ffs->ss_descs_count = counts[2];
|
||||||
|
ffs->ms_os_descs_count = os_descs_count;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -2268,6 +2473,85 @@ static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep,
|
||||||
return 0;
|
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,
|
static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
|
||||||
struct usb_configuration *c)
|
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) &&
|
const int super = gadget_is_superspeed(func->gadget) &&
|
||||||
func->ffs->ss_descs_count;
|
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 */
|
/* Make it a single chunk, less management later on */
|
||||||
vla_group(d);
|
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,
|
vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs,
|
||||||
super ? ffs->ss_descs_count + 1 : 0);
|
super ? ffs->ss_descs_count + 1 : 0);
|
||||||
vla_item_with_sz(d, short, inums, ffs->interfaces_count);
|
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);
|
vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length);
|
||||||
char *vlabuf;
|
char *vlabuf;
|
||||||
|
|
||||||
|
@ -2351,12 +2647,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
/* Allocate a single chunk, less management later on */
|
/* 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))
|
if (unlikely(!vlabuf))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Zero */
|
ffs->ms_os_descs_ext_prop_avail = vla_ptr(vlabuf, d, ext_prop);
|
||||||
memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz);
|
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 */
|
/* Copy descriptors */
|
||||||
memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
|
memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs,
|
||||||
ffs->raw_descs_length);
|
ffs->raw_descs_length);
|
||||||
|
@ -2410,12 +2710,16 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
||||||
|
|
||||||
if (likely(super)) {
|
if (likely(super)) {
|
||||||
func->function.ss_descriptors = vla_ptr(vlabuf, d, ss_descs);
|
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,
|
vla_ptr(vlabuf, d, raw_descs) + fs_len + hs_len,
|
||||||
d_raw_descs__sz - fs_len - hs_len,
|
d_raw_descs__sz - fs_len - hs_len,
|
||||||
__ffs_func_bind_do_descs, func);
|
__ffs_func_bind_do_descs, func);
|
||||||
if (unlikely(ret < 0))
|
if (unlikely(ss_len < 0)) {
|
||||||
|
ret = ss_len;
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ss_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2431,6 +2735,28 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
||||||
if (unlikely(ret < 0))
|
if (unlikely(ret < 0))
|
||||||
goto error;
|
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 */
|
/* And we're done */
|
||||||
ffs_event_add(ffs, FUNCTIONFS_BIND);
|
ffs_event_add(ffs, FUNCTIONFS_BIND);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2901,12 +3227,12 @@ static void *ffs_acquire_dev(const char *dev_name)
|
||||||
|
|
||||||
ffs_dev = _ffs_find_dev(dev_name);
|
ffs_dev = _ffs_find_dev(dev_name);
|
||||||
if (!ffs_dev)
|
if (!ffs_dev)
|
||||||
ffs_dev = ERR_PTR(-ENODEV);
|
ffs_dev = ERR_PTR(-ENOENT);
|
||||||
else if (ffs_dev->mounted)
|
else if (ffs_dev->mounted)
|
||||||
ffs_dev = ERR_PTR(-EBUSY);
|
ffs_dev = ERR_PTR(-EBUSY);
|
||||||
else if (ffs_dev->ffs_acquire_dev_callback &&
|
else if (ffs_dev->ffs_acquire_dev_callback &&
|
||||||
ffs_dev->ffs_acquire_dev_callback(ffs_dev))
|
ffs_dev->ffs_acquire_dev_callback(ffs_dev))
|
||||||
ffs_dev = ERR_PTR(-ENODEV);
|
ffs_dev = ERR_PTR(-ENOENT);
|
||||||
else
|
else
|
||||||
ffs_dev->mounted = true;
|
ffs_dev->mounted = true;
|
||||||
|
|
|
@ -68,6 +68,18 @@ struct f_ncm {
|
||||||
* callback and ethernet open/close
|
* callback and ethernet open/close
|
||||||
*/
|
*/
|
||||||
spinlock_t lock;
|
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)
|
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,
|
* 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
|
* 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
|
#define NTB_OUT_SIZE 16384
|
||||||
|
|
||||||
/*
|
/* Allocation for storing the NDP, 32 should suffice for a
|
||||||
* skbs of size less than that will not be aligned
|
* 16k packet. This allows a maximum of 32 * 507 Byte packets to
|
||||||
* to NCM's dwNtbInMaxSize to save bus bandwidth
|
* 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 | \
|
#define FORMATS_SUPPORTED (USB_CDC_NCM_NTB16_SUPPORTED | \
|
||||||
USB_CDC_NCM_NTB32_SUPPORTED)
|
USB_CDC_NCM_NTB32_SUPPORTED)
|
||||||
|
@ -355,14 +372,15 @@ struct ndp_parser_opts {
|
||||||
u32 ndp_sign;
|
u32 ndp_sign;
|
||||||
unsigned nth_size;
|
unsigned nth_size;
|
||||||
unsigned ndp_size;
|
unsigned ndp_size;
|
||||||
|
unsigned dpe_size;
|
||||||
unsigned ndplen_align;
|
unsigned ndplen_align;
|
||||||
/* sizes in u16 units */
|
/* sizes in u16 units */
|
||||||
unsigned dgram_item_len; /* index or length */
|
unsigned dgram_item_len; /* index or length */
|
||||||
unsigned block_length;
|
unsigned block_length;
|
||||||
unsigned fp_index;
|
unsigned ndp_index;
|
||||||
unsigned reserved1;
|
unsigned reserved1;
|
||||||
unsigned reserved2;
|
unsigned reserved2;
|
||||||
unsigned next_fp_index;
|
unsigned next_ndp_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define INIT_NDP16_OPTS { \
|
#define INIT_NDP16_OPTS { \
|
||||||
|
@ -370,13 +388,14 @@ struct ndp_parser_opts {
|
||||||
.ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \
|
.ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \
|
||||||
.nth_size = sizeof(struct usb_cdc_ncm_nth16), \
|
.nth_size = sizeof(struct usb_cdc_ncm_nth16), \
|
||||||
.ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \
|
.ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \
|
||||||
|
.dpe_size = sizeof(struct usb_cdc_ncm_dpe16), \
|
||||||
.ndplen_align = 4, \
|
.ndplen_align = 4, \
|
||||||
.dgram_item_len = 1, \
|
.dgram_item_len = 1, \
|
||||||
.block_length = 1, \
|
.block_length = 1, \
|
||||||
.fp_index = 1, \
|
.ndp_index = 1, \
|
||||||
.reserved1 = 0, \
|
.reserved1 = 0, \
|
||||||
.reserved2 = 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, \
|
.ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \
|
||||||
.nth_size = sizeof(struct usb_cdc_ncm_nth32), \
|
.nth_size = sizeof(struct usb_cdc_ncm_nth32), \
|
||||||
.ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \
|
.ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \
|
||||||
|
.dpe_size = sizeof(struct usb_cdc_ncm_dpe32), \
|
||||||
.ndplen_align = 8, \
|
.ndplen_align = 8, \
|
||||||
.dgram_item_len = 2, \
|
.dgram_item_len = 2, \
|
||||||
.block_length = 2, \
|
.block_length = 2, \
|
||||||
.fp_index = 2, \
|
.ndp_index = 2, \
|
||||||
.reserved1 = 1, \
|
.reserved1 = 1, \
|
||||||
.reserved2 = 2, \
|
.reserved2 = 2, \
|
||||||
.next_fp_index = 2, \
|
.next_ndp_index = 2, \
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
|
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) {
|
if (ncm->port.in_ep->driver_data) {
|
||||||
DBG(cdev, "reset ncm\n");
|
DBG(cdev, "reset ncm\n");
|
||||||
|
ncm->timer_stopping = true;
|
||||||
|
ncm->netdev = NULL;
|
||||||
gether_disconnect(&ncm->port);
|
gether_disconnect(&ncm->port);
|
||||||
ncm_reset_values(ncm);
|
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);
|
net = gether_connect(&ncm->port);
|
||||||
if (IS_ERR(net))
|
if (IS_ERR(net))
|
||||||
return PTR_ERR(net);
|
return PTR_ERR(net);
|
||||||
|
ncm->netdev = net;
|
||||||
|
ncm->timer_stopping = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&ncm->lock);
|
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;
|
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,
|
static struct sk_buff *ncm_wrap_ntb(struct gether *port,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct f_ncm *ncm = func_to_ncm(&port->func);
|
struct f_ncm *ncm = func_to_ncm(&port->func);
|
||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2 = NULL;
|
||||||
int ncb_len = 0;
|
int ncb_len = 0;
|
||||||
__le16 *tmp;
|
__le16 *ntb_data;
|
||||||
int div;
|
__le16 *ntb_ndp;
|
||||||
int rem;
|
int dgram_pad;
|
||||||
int pad;
|
|
||||||
int ndp_align;
|
|
||||||
int ndp_pad;
|
|
||||||
unsigned max_size = ncm->port.fixed_in_len;
|
unsigned max_size = ncm->port.fixed_in_len;
|
||||||
const struct ndp_parser_opts *opts = ncm->parser_opts;
|
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);
|
if (!skb && !ncm->skb_tx_data)
|
||||||
rem = le16_to_cpu(ntb_parameters.wNdpInPayloadRemainder);
|
return NULL;
|
||||||
ndp_align = le16_to_cpu(ntb_parameters.wNdpInAlignment);
|
|
||||||
|
|
||||||
ncb_len += opts->nth_size;
|
if (skb) {
|
||||||
ndp_pad = ALIGN(ncb_len, ndp_align) - ncb_len;
|
/* Add the CRC if required up front */
|
||||||
ncb_len += ndp_pad;
|
if (ncm->is_crc) {
|
||||||
ncb_len += opts->ndp_size;
|
uint32_t crc;
|
||||||
ncb_len += 2 * 2 * opts->dgram_item_len; /* Datagram entry */
|
__le16 *crc_pos;
|
||||||
ncb_len += 2 * 2 * opts->dgram_item_len; /* Zero datagram entry */
|
|
||||||
pad = ALIGN(ncb_len, div) + rem - ncb_len;
|
|
||||||
ncb_len += pad;
|
|
||||||
|
|
||||||
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);
|
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,
|
return skb2;
|
||||||
max_size - skb->len - ncb_len - crc_len,
|
|
||||||
GFP_ATOMIC);
|
|
||||||
dev_kfree_skb_any(skb);
|
|
||||||
if (!skb2)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
skb = skb2;
|
err:
|
||||||
|
ncm->netdev->stats.tx_dropped++;
|
||||||
|
|
||||||
tmp = (void *) skb_push(skb, ncb_len);
|
if (skb)
|
||||||
memset(tmp, 0, ncb_len);
|
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 */
|
return NULL;
|
||||||
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);
|
|
||||||
|
|
||||||
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 */
|
if (ncm->timer_stopping)
|
||||||
put_unaligned_le32(ncm->ndp_sign, tmp); /* dwSignature */
|
return;
|
||||||
tmp += 2;
|
|
||||||
/* wLength */
|
|
||||||
put_unaligned_le16(ncb_len - opts->nth_size - pad, tmp++);
|
|
||||||
|
|
||||||
tmp += opts->reserved1;
|
/* Only send if data is available. */
|
||||||
tmp += opts->next_fp_index; /* skip reserved (d)wNextFpIndex */
|
if (ncm->skb_tx_data) {
|
||||||
tmp += opts->reserved2;
|
ncm->timer_force_tx = true;
|
||||||
|
ncm->netdev->netdev_ops->ndo_start_xmit(NULL, ncm->netdev);
|
||||||
if (ncm->is_crc) {
|
ncm->timer_force_tx = false;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* (d)wDatagramIndex[0] */
|
/*
|
||||||
put_ncm(&tmp, opts->dgram_item_len, ncb_len);
|
* The transmit should only be run if no skb data has been sent
|
||||||
/* (d)wDatagramLength[0] */
|
* for a certain duration.
|
||||||
put_ncm(&tmp, opts->dgram_item_len, skb->len - ncb_len);
|
*/
|
||||||
/* (d)wDatagramIndex[1] and (d)wDatagramLength[1] already zeroed */
|
static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
|
||||||
|
{
|
||||||
if (skb->len > MAX_TX_NONFIXED)
|
struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
|
||||||
memset(skb_put(skb, max_size - skb->len),
|
tasklet_schedule(&ncm->tx_tasklet);
|
||||||
0, max_size - skb->len);
|
return HRTIMER_NORESTART;
|
||||||
|
|
||||||
return skb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ncm_unwrap_ntb(struct gether *port,
|
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);
|
struct f_ncm *ncm = func_to_ncm(&port->func);
|
||||||
__le16 *tmp = (void *) skb->data;
|
__le16 *tmp = (void *) skb->data;
|
||||||
unsigned index, index2;
|
unsigned index, index2;
|
||||||
|
int ndp_index;
|
||||||
unsigned dg_len, dg_len2;
|
unsigned dg_len, dg_len2;
|
||||||
unsigned ndp_len;
|
unsigned ndp_len;
|
||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2;
|
||||||
|
@ -995,91 +1157,101 @@ static int ncm_unwrap_ntb(struct gether *port,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = get_ncm(&tmp, opts->fp_index);
|
ndp_index = get_ncm(&tmp, opts->ndp_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;
|
|
||||||
|
|
||||||
|
/* Run through all the NDP's in the NTB */
|
||||||
do {
|
do {
|
||||||
index = index2;
|
/* NCM 3.2 */
|
||||||
dg_len = dg_len2;
|
if (((ndp_index % 4) != 0) &&
|
||||||
if (dg_len < 14 + crc_len) { /* ethernet header + crc */
|
(ndp_index < opts->nth_size)) {
|
||||||
INFO(port->func.config->cdev, "Bad dgram length: %x\n",
|
INFO(port->func.config->cdev, "Bad index: %#X\n",
|
||||||
dg_len);
|
ndp_index);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (ncm->is_crc) {
|
|
||||||
uint32_t crc, crc2;
|
|
||||||
|
|
||||||
crc = get_unaligned_le32(skb->data +
|
/* walk through NDP */
|
||||||
index + dg_len - crc_len);
|
tmp = (void *)(skb->data + ndp_index);
|
||||||
crc2 = ~crc32_le(~0,
|
if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
|
||||||
skb->data + index,
|
INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
|
||||||
dg_len - crc_len);
|
goto err;
|
||||||
if (crc != crc2) {
|
|
||||||
INFO(port->func.config->cdev, "Bad CRC\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);
|
index2 = get_ncm(&tmp, opts->dgram_item_len);
|
||||||
dg_len2 = 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) {
|
do {
|
||||||
skb2 = skb;
|
index = index2;
|
||||||
} else {
|
dg_len = dg_len2;
|
||||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
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)
|
if (skb2 == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
memcpy(skb_put(skb2, dg_len - crc_len),
|
||||||
|
skb->data + index, dg_len - crc_len);
|
||||||
|
|
||||||
if (!skb_pull(skb2, index)) {
|
skb_queue_tail(list, skb2);
|
||||||
ret = -EOVERFLOW;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
skb_trim(skb2, dg_len - crc_len);
|
ndp_len -= 2 * (opts->dgram_item_len * 2);
|
||||||
skb_queue_tail(list, skb2);
|
|
||||||
|
|
||||||
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)
|
dev_kfree_skb_any(skb);
|
||||||
break;
|
|
||||||
} while (ndp_len > 2 * (opts->dgram_item_len * 2)); /* zero entry */
|
|
||||||
|
|
||||||
VDBG(port->func.config->cdev,
|
VDBG(port->func.config->cdev,
|
||||||
"Parsed NTB with %d frames\n", dgram_counter);
|
"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");
|
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);
|
gether_disconnect(&ncm->port);
|
||||||
|
}
|
||||||
|
|
||||||
if (ncm->notify->driver_data) {
|
if (ncm->notify->driver_data) {
|
||||||
usb_ep_disable(ncm->notify);
|
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.open = ncm_open;
|
||||||
ncm->port.close = ncm_close;
|
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",
|
DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
|
||||||
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||||
ncm->port.in_ep->name, ncm->port.out_ep->name,
|
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");
|
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);
|
usb_free_all_descriptors(f);
|
||||||
|
|
||||||
kfree(ncm->notify_req->buf);
|
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);
|
ncm->port.ioport = netdev_priv(opts->net);
|
||||||
mutex_unlock(&opts->lock);
|
mutex_unlock(&opts->lock);
|
||||||
ncm->port.is_fixed = true;
|
ncm->port.is_fixed = true;
|
||||||
|
ncm->port.supports_multi_frame = true;
|
||||||
|
|
||||||
ncm->port.func.name = "cdc_network";
|
ncm->port.func.name = "cdc_network";
|
||||||
/* descriptors are per-instance copies */
|
/* 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_control_intf.bInterfaceNumber = status;
|
||||||
rndis_union_desc.bMasterInterface0 = 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);
|
status = usb_interface_id(c, f);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto fail;
|
goto fail;
|
|
@ -348,14 +348,34 @@ static int uac2_pcm_open(struct snd_pcm_substream *substream)
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
spin_lock_init(&uac2->p_prm.lock);
|
spin_lock_init(&uac2->p_prm.lock);
|
||||||
runtime->hw.rate_min = p_srate;
|
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.channels_min = num_channels(p_chmask);
|
||||||
runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
|
runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
|
||||||
/ runtime->hw.periods_min;
|
/ runtime->hw.periods_min;
|
||||||
} else {
|
} else {
|
||||||
spin_lock_init(&uac2->c_prm.lock);
|
spin_lock_init(&uac2->c_prm.lock);
|
||||||
runtime->hw.rate_min = c_srate;
|
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.channels_min = num_channels(c_chmask);
|
||||||
runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
|
runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
|
||||||
/ runtime->hw.periods_min;
|
/ runtime->hw.periods_min;
|
|
@ -483,7 +483,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
|
||||||
struct net_device *net)
|
struct net_device *net)
|
||||||
{
|
{
|
||||||
struct eth_dev *dev = netdev_priv(net);
|
struct eth_dev *dev = netdev_priv(net);
|
||||||
int length = skb->len;
|
int length = 0;
|
||||||
int retval;
|
int retval;
|
||||||
struct usb_request *req = NULL;
|
struct usb_request *req = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -500,13 +500,13 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
|
|
||||||
if (!in) {
|
if (skb && !in) {
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply outgoing CDC or RNDIS filters */
|
/* apply outgoing CDC or RNDIS filters */
|
||||||
if (!is_promisc(cdc_filter)) {
|
if (skb && !is_promisc(cdc_filter)) {
|
||||||
u8 *dest = skb->data;
|
u8 *dest = skb->data;
|
||||||
|
|
||||||
if (is_multicast_ether_addr(dest)) {
|
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)
|
if (dev->port_usb)
|
||||||
skb = dev->wrap(dev->port_usb, skb);
|
skb = dev->wrap(dev->port_usb, skb);
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
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;
|
goto drop;
|
||||||
|
}
|
||||||
length = skb->len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
length = skb->len;
|
||||||
req->buf = skb->data;
|
req->buf = skb->data;
|
||||||
req->context = skb;
|
req->context = skb;
|
||||||
req->complete = tx_complete;
|
req->complete = tx_complete;
|
||||||
|
@ -604,6 +610,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
drop:
|
drop:
|
||||||
dev->net->stats.tx_dropped++;
|
dev->net->stats.tx_dropped++;
|
||||||
|
multiframe:
|
||||||
spin_lock_irqsave(&dev->req_lock, flags);
|
spin_lock_irqsave(&dev->req_lock, flags);
|
||||||
if (list_empty(&dev->tx_reqs))
|
if (list_empty(&dev->tx_reqs))
|
||||||
netif_start_queue(net);
|
netif_start_queue(net);
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/usb/composite.h>
|
#include <linux/usb/composite.h>
|
||||||
#include <linux/usb/cdc.h>
|
#include <linux/usb/cdc.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
|
||||||
#include "gadget_chips.h"
|
#include "gadget_chips.h"
|
||||||
|
|
||||||
|
@ -74,6 +75,7 @@ struct gether {
|
||||||
bool is_fixed;
|
bool is_fixed;
|
||||||
u32 fixed_out_len;
|
u32 fixed_out_len;
|
||||||
u32 fixed_in_len;
|
u32 fixed_in_len;
|
||||||
|
bool supports_multi_frame;
|
||||||
struct sk_buff *(*wrap)(struct gether *port,
|
struct sk_buff *(*wrap)(struct gether *port,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
int (*unwrap)(struct gether *port,
|
int (*unwrap)(struct gether *port,
|
|
@ -216,6 +216,13 @@ struct ffs_data {
|
||||||
unsigned fs_descs_count;
|
unsigned fs_descs_count;
|
||||||
unsigned hs_descs_count;
|
unsigned hs_descs_count;
|
||||||
unsigned ss_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 strings_count;
|
||||||
unsigned short interfaces_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),
|
.unbind = __exit_p(acm_ms_unbind),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module_usb_composite_driver(acm_ms_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_AUTHOR("Klaus Schwarzkopf <schwarzkopf@sensortherm.de>");
|
MODULE_AUTHOR("Klaus Schwarzkopf <schwarzkopf@sensortherm.de>");
|
||||||
MODULE_LICENSE("GPL v2");
|
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),
|
.unbind = __exit_p(audio_unbind),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init init(void)
|
module_usb_composite_driver(audio_driver);
|
||||||
{
|
|
||||||
return usb_composite_probe(&audio_driver);
|
|
||||||
}
|
|
||||||
module_init(init);
|
|
||||||
|
|
||||||
static void __exit cleanup(void)
|
|
||||||
{
|
|
||||||
usb_composite_unregister(&audio_driver);
|
|
||||||
}
|
|
||||||
module_exit(cleanup);
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_AUTHOR("Bryan Wu <cooloney@kernel.org>");
|
MODULE_AUTHOR("Bryan Wu <cooloney@kernel.org>");
|
|
@ -231,18 +231,8 @@ static __refdata struct usb_composite_driver cdc_driver = {
|
||||||
.unbind = __exit_p(cdc_unbind),
|
.unbind = __exit_p(cdc_unbind),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module_usb_composite_driver(cdc_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_AUTHOR("David Brownell");
|
MODULE_AUTHOR("David Brownell");
|
||||||
MODULE_LICENSE("GPL");
|
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),
|
.unbind = __exit_p(eth_unbind),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module_usb_composite_driver(eth_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
|
MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
|
||||||
MODULE_AUTHOR("David Brownell, Benedikt Spanger");
|
MODULE_AUTHOR("David Brownell, Benedikt Spanger");
|
||||||
MODULE_LICENSE("GPL");
|
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)
|
static void *functionfs_acquire_dev(struct ffs_dev *dev)
|
||||||
{
|
{
|
||||||
if (!try_module_get(THIS_MODULE))
|
if (!try_module_get(THIS_MODULE))
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -163,15 +163,4 @@ static __refdata struct usb_composite_driver midi_driver = {
|
||||||
.unbind = __exit_p(midi_unbind),
|
.unbind = __exit_p(midi_unbind),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init midi_init(void)
|
module_usb_composite_driver(midi_driver);
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
|
@ -507,15 +507,4 @@ static __refdata struct usb_composite_driver multi_driver = {
|
||||||
.needs_serial = 1,
|
.needs_serial = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module_usb_composite_driver(multi_driver);
|
||||||
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);
|
|
|
@ -204,18 +204,8 @@ static __refdata struct usb_composite_driver ncm_driver = {
|
||||||
.unbind = __exit_p(gncm_unbind),
|
.unbind = __exit_p(gncm_unbind),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module_usb_composite_driver(ncm_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_AUTHOR("Yauheni Kaliuta");
|
MODULE_AUTHOR("Yauheni Kaliuta");
|
||||||
MODULE_LICENSE("GPL");
|
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),
|
.unbind = __exit_p(nokia_unbind),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init nokia_init(void)
|
module_usb_composite_driver(nokia_driver);
|
||||||
{
|
|
||||||
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);
|
|
|
@ -390,20 +390,7 @@ static __refdata struct usb_composite_driver webcam_driver = {
|
||||||
.unbind = webcam_unbind,
|
.unbind = webcam_unbind,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init
|
module_usb_composite_driver(webcam_driver);
|
||||||
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_AUTHOR("Laurent Pinchart");
|
MODULE_AUTHOR("Laurent Pinchart");
|
||||||
MODULE_DESCRIPTION("Webcam Video Gadget");
|
MODULE_DESCRIPTION("Webcam Video Gadget");
|
|
@ -411,17 +411,7 @@ static __refdata struct usb_composite_driver zero_driver = {
|
||||||
.resume = zero_resume,
|
.resume = zero_resume,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module_usb_composite_driver(zero_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("David Brownell");
|
MODULE_AUTHOR("David Brownell");
|
||||||
MODULE_LICENSE("GPL");
|
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_LINK 6
|
||||||
#define USB_EXT_PROP_UNICODE_MULTI 7
|
#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)
|
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)
|
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)
|
static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
|
||||||
{
|
{
|
||||||
int result;
|
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,
|
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)
|
if (result < 0)
|
||||||
return result;
|
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;
|
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,
|
static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
|
||||||
int data_len)
|
int data_len)
|
||||||
{
|
{
|
||||||
put_unaligned_le32(data_len,
|
put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
|
||||||
&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
|
memcpy(usb_ext_prop_data_ptr(buf, pnl), data, data_len);
|
||||||
memcpy(&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl], data, data_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
|
static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
|
||||||
int data_len)
|
int data_len)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
put_unaligned_le32(data_len,
|
put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
|
||||||
&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
|
|
||||||
|
|
||||||
result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
|
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);
|
data_len - 2);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
put_unaligned_le16(0,
|
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;
|
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;
|
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 resource *regs, *fifo;
|
||||||
struct clk *pclk, *hclk;
|
struct clk *pclk, *hclk;
|
|
@ -18,6 +18,8 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#include "fsl_usb2_udc.h"
|
||||||
|
|
||||||
static struct clk *mxc_ahb_clk;
|
static struct clk *mxc_ahb_clk;
|
||||||
static struct clk *mxc_per_clk;
|
static struct clk *mxc_per_clk;
|
||||||
static struct clk *mxc_ipg_clk;
|
static struct clk *mxc_ipg_clk;
|
|
@ -2539,7 +2539,7 @@ static int qe_udc_probe(struct platform_device *ofdev)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
/* create a buf for ZLP send, need to remain zeroed */
|
/* 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) {
|
if (udc->nullbuf == NULL) {
|
||||||
dev_err(udc->dev, "cannot alloc nullbuf\n");
|
dev_err(udc->dev, "cannot alloc nullbuf\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -2547,10 +2547,10 @@ static int qe_udc_probe(struct platform_device *ofdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* buffer for data of get_status request */
|
/* 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) {
|
if (udc->statusbuf == NULL) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err4;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
udc->nullp = virt_to_phys((void *)udc->nullbuf);
|
udc->nullp = virt_to_phys((void *)udc->nullbuf);
|
||||||
|
@ -2581,13 +2581,13 @@ static int qe_udc_probe(struct platform_device *ofdev)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(udc->dev, "cannot request irq %d err %d\n",
|
dev_err(udc->dev, "cannot request irq %d err %d\n",
|
||||||
udc->usb_irq, ret);
|
udc->usb_irq, ret);
|
||||||
goto err5;
|
goto err4;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
|
ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
|
||||||
qe_udc_release);
|
qe_udc_release);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err6;
|
goto err5;
|
||||||
|
|
||||||
platform_set_drvdata(ofdev, udc);
|
platform_set_drvdata(ofdev, udc);
|
||||||
dev_info(udc->dev,
|
dev_info(udc->dev,
|
||||||
|
@ -2595,9 +2595,9 @@ static int qe_udc_probe(struct platform_device *ofdev)
|
||||||
(udc->soc_type == PORT_QE) ? "QE" : "CPM");
|
(udc->soc_type == PORT_QE) ? "QE" : "CPM");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err6:
|
|
||||||
free_irq(udc->usb_irq, udc);
|
|
||||||
err5:
|
err5:
|
||||||
|
free_irq(udc->usb_irq, udc);
|
||||||
|
err4:
|
||||||
irq_dispose_mapping(udc->usb_irq);
|
irq_dispose_mapping(udc->usb_irq);
|
||||||
err_noirq:
|
err_noirq:
|
||||||
if (udc->nullmap) {
|
if (udc->nullmap) {
|
||||||
|
@ -2610,9 +2610,6 @@ err_noirq:
|
||||||
udc->nullp, 256,
|
udc->nullp, 256,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
kfree(udc->statusbuf);
|
|
||||||
err4:
|
|
||||||
kfree(udc->nullbuf);
|
|
||||||
err3:
|
err3:
|
||||||
ep = &udc->eps[0];
|
ep = &udc->eps[0];
|
||||||
cpm_muram_free(cpm_muram_offset(ep->rxbase));
|
cpm_muram_free(cpm_muram_offset(ep->rxbase));
|
||||||
|
@ -2660,8 +2657,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
|
||||||
udc->nullp, 256,
|
udc->nullp, 256,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
kfree(udc->statusbuf);
|
|
||||||
kfree(udc->nullbuf);
|
|
||||||
|
|
||||||
ep = &udc->eps[0];
|
ep = &udc->eps[0];
|
||||||
cpm_muram_free(cpm_muram_offset(ep->rxbase));
|
cpm_muram_free(cpm_muram_offset(ep->rxbase));
|
|
@ -59,9 +59,9 @@
|
||||||
static const char driver_name[] = "fsl-usb2-udc";
|
static const char driver_name[] = "fsl-usb2-udc";
|
||||||
static const char driver_desc[] = DRIVER_DESC;
|
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() */
|
/* it is initialized in probe() */
|
||||||
static struct fsl_udc *udc_controller = NULL;
|
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.
|
* request is still in progress.
|
||||||
*--------------------------------------------------------------*/
|
*--------------------------------------------------------------*/
|
||||||
static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
|
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;
|
struct fsl_udc *udc = NULL;
|
||||||
unsigned char stopped = ep->stopped;
|
unsigned char stopped = ep->stopped;
|
||||||
|
@ -1392,6 +1394,8 @@ stall:
|
||||||
|
|
||||||
static void setup_received_irq(struct fsl_udc *udc,
|
static void setup_received_irq(struct fsl_udc *udc,
|
||||||
struct usb_ctrlrequest *setup)
|
struct usb_ctrlrequest *setup)
|
||||||
|
__releases(udc->lock)
|
||||||
|
__acquires(udc->lock)
|
||||||
{
|
{
|
||||||
u16 wValue = le16_to_cpu(setup->wValue);
|
u16 wValue = le16_to_cpu(setup->wValue);
|
||||||
u16 wIndex = le16_to_cpu(setup->wIndex);
|
u16 wIndex = le16_to_cpu(setup->wIndex);
|
||||||
|
@ -1957,8 +1961,7 @@ static int fsl_udc_start(struct usb_gadget *g,
|
||||||
&udc_controller->gadget);
|
&udc_controller->gadget);
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
ERR("can't bind to transceiver\n");
|
ERR("can't bind to transceiver\n");
|
||||||
driver->unbind(&udc_controller->gadget);
|
udc_controller->driver = NULL;
|
||||||
udc_controller->driver = 0;
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2246,7 +2249,7 @@ static void fsl_udc_release(struct device *dev)
|
||||||
* init resource for globle controller
|
* init resource for globle controller
|
||||||
* Return the udc handle on success or NULL on failure
|
* 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 platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct fsl_usb2_platform_data *pdata;
|
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
|
* ep0out is not used so do nothing here
|
||||||
* ep0in should be taken care
|
* 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)
|
char *name, int link)
|
||||||
{
|
{
|
||||||
struct fsl_ep *ep = &udc->eps[index];
|
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
|
* all intialization operations implemented here except enabling usb_intr reg
|
||||||
* board setup should have been done in the platform code
|
* 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 fsl_usb2_platform_data *pdata;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
@ -2380,7 +2383,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
|
||||||
goto err_release_mem_region;
|
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.
|
* do platform specific init: check the clock, grab/config pins, etc.
|
|
@ -12,6 +12,9 @@
|
||||||
#ifndef __FSL_USB2_UDC_H
|
#ifndef __FSL_USB2_UDC_H
|
||||||
#define __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 registers here
|
||||||
*/
|
*/
|
||||||
#define USB_MAX_CTRL_PAYLOAD 64
|
#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);
|
struct fusb300 *fusb300 = to_fusb300(g);
|
||||||
|
|
||||||
driver->unbind(&fusb300->gadget);
|
|
||||||
|
|
||||||
init_controller(fusb300);
|
init_controller(fusb300);
|
||||||
fusb300->driver = NULL;
|
fusb300->driver = NULL;
|
||||||
|
|
||||||
|
@ -1359,7 +1357,7 @@ static int __exit fusb300_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init fusb300_probe(struct platform_device *pdev)
|
static int fusb300_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *res, *ires, *ires1;
|
struct resource *res, *ires, *ires1;
|
||||||
void __iomem *reg = NULL;
|
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