From adfc17bf09ba67cff11472ffa58fc0208defa29c Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Fri, 18 Apr 2014 09:48:24 +0200
Subject: usb:gadget:f_thor: code cleanup in function download_tail()
In thor's download_tail() function, dfu_get_entity() is called
before each dfu_write() call and the returned entity pointers
are the same. So dfu_get_entity() can be called just once and
this patch changes this.
Signed-off-by: Przemyslaw Marczak
Cc: Lukasz Majewski
Cc: Marek Vasut
Cc: Heiko Schocher
Cc: Tom Rini
---
drivers/usb/gadget/f_thor.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index f5c0224f21..231f9c0ac7 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -204,14 +204,14 @@ static long long int download_head(unsigned long long total,
static int download_tail(long long int left, int cnt)
{
+ struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num);
void *transfer_buffer = dfu_get_buf();
int ret;
debug("%s: left: %llu cnt: %d\n", __func__, left, cnt);
if (left) {
- ret = dfu_write(dfu_get_entity(alt_setting_num),
- transfer_buffer, left, cnt++);
+ ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++);
if (ret) {
error("DFU write failed [%d]: left: %llu", ret, left);
return ret;
@@ -225,8 +225,7 @@ static int download_tail(long long int left, int cnt)
* This also frees memory malloc'ed by dfu_get_buf(), so no explicit
* need fo call dfu_free_buf() is needed.
*/
- ret = dfu_write(dfu_get_entity(alt_setting_num),
- transfer_buffer, 0, cnt);
+ ret = dfu_write(dfu_entity, transfer_buffer, 0, cnt);
if (ret)
error("DFU write failed [%d] cnt: %d", ret, cnt);
--
cgit
From fd2a89b20ba66d76929f672b03f392733fb1b2a6 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Fri, 18 Apr 2014 09:48:25 +0200
Subject: usb:gadget:f_thor: fix write to filesystem by add dfu_flush()
Since dfu read/write operations needs to be flushed manually,
writing to filesystem on MMC by thor was broken. MMC raw write
actually is working fine because current dfu_flush() function
writes filesystem only. This commit adds dfu_flush() to f_thor
and now filesystem write is working.
This change was tested on Trats2 board.
Signed-off-by: Przemyslaw Marczak
Cc: Lukasz Majewski
Cc: Marek Vasut
Cc: Heiko Schocher
Cc: Tom Rini
---
drivers/usb/gadget/f_thor.c | 6 ++++++
1 file changed, 6 insertions(+)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index 231f9c0ac7..ba47945007 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -229,6 +229,12 @@ static int download_tail(long long int left, int cnt)
if (ret)
error("DFU write failed [%d] cnt: %d", ret, cnt);
+ ret = dfu_flush(dfu_entity, transfer_buffer, 0, cnt);
+ if (ret) {
+ error("DFU flush failed!");
+ return ret;
+ }
+
return ret;
}
--
cgit
From 52d45012ff66dee716b8dfcb7d67d3ab54a3208a Mon Sep 17 00:00:00 2001
From: Rob Herring
Date: Fri, 18 Apr 2014 08:54:28 -0500
Subject: usb: handle NULL table in usb_gadget_get_string
Allow a NULL table to be passed to usb_gadget_get_string for cases
when a string table may not be populated.
Signed-off-by: Rob Herring
Reviewed-by: Tom Rini
Acked-by: Marek Vasut
Acked-by: Lukasz Majewski
---
drivers/usb/gadget/usbstring.c | 3 +++
1 file changed, 3 insertions(+)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index de5fa3f648..8c3ff64fe3 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -108,6 +108,9 @@ usb_gadget_get_string(struct usb_gadget_strings *table, int id, u8 *buf)
struct usb_string *s;
int len;
+ if (!table)
+ return -EINVAL;
+
/* descriptor 0 has the language id */
if (id == 0) {
buf[0] = 4;
--
cgit
From f5c03006dd1794362a2be7136fed9e664bc1775b Mon Sep 17 00:00:00 2001
From: Stephen Warren
Date: Thu, 24 Apr 2014 17:52:36 -0600
Subject: usb: ci_udc: Support larger packets
ci_ep_queue() currently only fills in the page0/page1 fields in the
queue item. If the buffer is larger than 4KiB (unaligned) or 8KiB
(page-aligned), then this prevents the HW from knowing where to write
the balance of the data.
Fix this by initializing all 5 pageN pointers, which allows up to
16KiB (potentially non-page-aligned) buffers.
Signed-off-by: Stephen Warren
---
drivers/usb/gadget/ci_udc.c | 3 +++
1 file changed, 3 insertions(+)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 14b1e9b8bf..815ce7b262 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -350,6 +350,9 @@ static int ci_ep_queue(struct usb_ep *ep,
item->info = INFO_BYTES(len) | INFO_IOC | INFO_ACTIVE;
item->page0 = (uint32_t)ci_ep->b_buf;
item->page1 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x1000;
+ item->page2 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x2000;
+ item->page3 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x3000;
+ item->page4 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x4000;
ci_flush_qtd(num);
head->next = (unsigned) item;
--
cgit
From 8aac6e9c537a2dd0c76acc3a0768ae7af5e166ab Mon Sep 17 00:00:00 2001
From: Stephen Warren
Date: Thu, 24 Apr 2014 17:52:37 -0600
Subject: usb: ci_udc: set ep->req.actual after transfer
At least drivers/usb/gadget/storage_common.c expects that ep->req.actual
contain the number of bytes actually transferred. (At least in practice,
I observed it failing to work correctly unless this was the case).
However, ci_udc.c modifies ep->req.length instead. I assume that .length
is supposed to represent the allocated buffer size, whereas .actual is
supposed to represent the actual number of bytes transferred. In the OUT
transaction case, this may happen simply because the host sends a smaller
packet than the max possible size, which is quite legal. In the IN case,
transferring fewer bytes than requested could presumably happen as an
error.
Modify handle_ep_complete() to write to .actual rather than modifying
.length.
Signed-off-by: Stephen Warren
---
drivers/usb/gadget/ci_udc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 815ce7b262..832606f5e4 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -321,7 +321,7 @@ static void ci_debounce(struct ci_ep *ep, int in)
if (addr == ba)
return; /* not a bounce */
- memcpy(ep->req.buf, ep->b_buf, ep->req.length);
+ memcpy(ep->req.buf, ep->b_buf, ep->req.actual);
free:
/* Large payloads use allocated buffer, free it. */
if (ep->b_buf != ep->b_fast)
@@ -388,7 +388,7 @@ static void handle_ep_complete(struct ci_ep *ep)
num, in ? "in" : "out", item->info, item->page0);
len = (item->info >> 16) & 0x7fff;
- ep->req.length -= len;
+ ep->req.actual = ep->req.length - len;
ci_debounce(ep, in);
DBG("ept%d %s complete %x\n",
--
cgit
From 0c51dc6db9ea0e3912d1d3e2d953bc22de433c60 Mon Sep 17 00:00:00 2001
From: Stephen Warren
Date: Thu, 24 Apr 2014 17:52:38 -0600
Subject: usb: ci_udc: make PHY initialization conditional
usb_gadget_register_driver() currently unconditionally programs PORTSC
to select a ULPI PHY. This is incorrect on at least the Tegra boards I
am testing with, which use a UTMI PHY for the OTG ports. Make the PHY
selection code conditional upon the specific EHCI controller that is in
use.
Ideally, I believe that the PHY initialization code should be part of
ehci_hcd_init() in the relevant EHCI controller driver, or some board-
specific function that ehci_hcd_init() calls.
For MX6, I'm not sure this PHY initialization code is correct even before
this patch, since ehci-mx6's ehci_hcd_init() already configures PORTSC to
a board-specific value, and it seems likely that the code in ci_udc.c is
incorrectly undoing this. Perhaps this is not an issue if the PHY
selection register bits aren't implemented on this instance of the MX6
USB controller?
ehci-mxs.c doens't appear to touch PORTSC, so this code is likely still
required there.
Signed-off-by: Stephen Warren
---
drivers/usb/gadget/ci_udc.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 832606f5e4..fd751a2426 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -702,7 +702,6 @@ static int ci_udc_probe(void)
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
- struct ci_udc *udc;
int ret;
if (!driver)
@@ -717,12 +716,18 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
return ret;
ret = ci_udc_probe();
+#if defined(CONFIG_USB_EHCI_MX6) || defined(CONFIG_USB_EHCI_MXS)
+ /*
+ * FIXME: usb_lowlevel_init()->ehci_hcd_init() should be doing all
+ * HW-specific initialization, e.g. ULPI-vs-UTMI PHY selection
+ */
if (!ret) {
- udc = (struct ci_udc *)controller.ctrl->hcor;
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
/* select ULPI phy */
writel(PTS(PTS_ENABLE) | PFSC, &udc->portsc);
}
+#endif
ret = driver->bind(&controller.gadget);
if (ret) {
--
cgit
From fcf2ede190e054edcb804ba7786dd024b388a160 Mon Sep 17 00:00:00 2001
From: Stephen Warren
Date: Thu, 24 Apr 2014 17:52:39 -0600
Subject: usb: ci_udc: support variants with hostpc register
Tegra's USB controller appears to be a variant of the ChipIdea
controller; perhaps derived from it, or simply a different version of
the IP core to what U-Boot supports today.
In this variant, at least the following difference are present:
- Some registers are moved about.
- Setup transaction completion is reported in a separate 'epsetupstat'
register, rather than in 'epstat' (which still exists, perhaps for
other transaction types).
- USB connection speed is reported in a separate 'hostpc1_devlc'
register, rather than 'portsc'.
- The registers used by ci_udc.c begin at offset 0x130 from the USB
register base, rather than offset 0x140. However, this is handled
by the associated EHCI controller driver, since the register address
is stored in controller.ctrl->hcor.
Introduce define CONFIG_CI_UDC_HAS_HOSTPC to indicate which variant of
the controller should be supported. The "HAS_HOSTPC" part of this name
mirrors the similar "has_hostpc" field used by the Linux EHCI controller
core to represent the presence/absence of the hostpc1_devlc register.
Signed-off-by: Stephen Warren
---
drivers/usb/gadget/ci_udc.c | 15 +++++++++++
drivers/usb/gadget/ci_udc.h | 65 ++++++++++++++++++++++++++++++++-------------
2 files changed, 62 insertions(+), 18 deletions(-)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index fd751a2426..02d3fdade8 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -416,7 +416,11 @@ static void handle_setup(void)
ci_invalidate_qh(0);
memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest));
+#ifdef CONFIG_CI_UDC_HAS_HOSTPC
+ writel(EPT_RX(0), &udc->epsetupstat);
+#else
writel(EPT_RX(0), &udc->epstat);
+#endif
DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest),
r.bRequestType, r.bRequest, r.wIndex, r.wValue);
@@ -483,6 +487,9 @@ static void stop_activity(void)
struct ept_queue_head *head;
struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
writel(readl(&udc->epcomp), &udc->epcomp);
+#ifdef CONFIG_CI_UDC_HAS_HOSTPC
+ writel(readl(&udc->epsetupstat), &udc->epsetupstat);
+#endif
writel(readl(&udc->epstat), &udc->epstat);
writel(0xffffffff, &udc->epflush);
@@ -524,7 +531,11 @@ void udc_irq(void)
int max = 64;
int speed = USB_SPEED_FULL;
+#ifdef CONFIG_CI_UDC_HAS_HOSTPC
+ bit = (readl(&udc->hostpc1_devlc) >> 25) & 3;
+#else
bit = (readl(&udc->portsc) >> 26) & 3;
+#endif
DBG("-- portchange %x %s\n", bit, (bit == 2) ? "High" : "Full");
if (bit == 2) {
speed = USB_SPEED_HIGH;
@@ -541,7 +552,11 @@ void udc_irq(void)
printf("\n", readl(&udc->epcomp));
if ((n & STS_UI) || (n & STS_UEI)) {
+#ifdef CONFIG_CI_UDC_HAS_HOSTPC
+ n = readl(&udc->epsetupstat);
+#else
n = readl(&udc->epstat);
+#endif
if (n & EPT_RX(0))
handle_setup();
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 42f6ef4ab3..4425fd9345 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -8,45 +8,74 @@
#define NUM_ENDPOINTS 6
+#ifdef CONFIG_CI_UDC_HAS_HOSTPC
+struct ci_udc {
+ u32 usbcmd; /* 0x130 */
+ u32 usbsts; /* 0x134 */
+ u32 pad1[3];
+ u32 devaddr; /* 0x144 */
+ u32 epinitaddr; /* 0x148 */
+ u32 pad2[10];
+ u32 portsc; /* 0x174 */
+ u32 pad178[(0x1b4 - (0x174 + 4)) / 4];
+ u32 hostpc1_devlc; /* 0x1b4 */
+ u32 pad1b8[(0x1f8 - (0x1b4 + 4)) / 4];
+ u32 usbmode; /* 0x1f8 */
+ u32 pad1fc[(0x208 - (0x1f8 + 4)) / 4];
+ u32 epsetupstat; /* 0x208 */
+ u32 epprime; /* 0x20c */
+ u32 epflush; /* 0x210 */
+ u32 epstat; /* 0x214 */
+ u32 epcomp; /* 0x218 */
+ u32 epctrl[16]; /* 0x21c */
+};
+#else
struct ci_udc {
-#define MICRO_8FRAME 0x8
-#define USBCMD_ITC(x) ((((x) > 0xff) ? 0xff : x) << 16)
-#define USBCMD_FS2 (1 << 15)
-#define USBCMD_RST (1 << 1)
-#define USBCMD_RUN (1)
u32 usbcmd; /* 0x140 */
-#define STS_SLI (1 << 8)
-#define STS_URI (1 << 6)
-#define STS_PCI (1 << 2)
-#define STS_UEI (1 << 1)
-#define STS_UI (1 << 0)
u32 usbsts; /* 0x144 */
u32 pad1[3];
u32 devaddr; /* 0x154 */
u32 epinitaddr; /* 0x158 */
u32 pad2[10];
-#define PTS_ENABLE 2
-#define PTS(x) (((x) & 0x3) << 30)
-#define PFSC (1 << 24)
u32 portsc; /* 0x184 */
u32 pad3[8];
-#define USBMODE_DEVICE 2
u32 usbmode; /* 0x1a8 */
u32 epstat; /* 0x1ac */
-#define EPT_TX(x) (1 << (((x) & 0xffff) + 16))
-#define EPT_RX(x) (1 << ((x) & 0xffff))
u32 epprime; /* 0x1b0 */
u32 epflush; /* 0x1b4 */
u32 pad4;
u32 epcomp; /* 0x1bc */
+ u32 epctrl[16]; /* 0x1c0 */
+};
+
+#define PTS_ENABLE 2
+#define PTS(x) (((x) & 0x3) << 30)
+#define PFSC (1 << 24)
+#endif
+
+#define MICRO_8FRAME 0x8
+#define USBCMD_ITC(x) ((((x) > 0xff) ? 0xff : x) << 16)
+#define USBCMD_FS2 (1 << 15)
+#define USBCMD_RST (1 << 1)
+#define USBCMD_RUN (1)
+
+#define STS_SLI (1 << 8)
+#define STS_URI (1 << 6)
+#define STS_PCI (1 << 2)
+#define STS_UEI (1 << 1)
+#define STS_UI (1 << 0)
+
+#define USBMODE_DEVICE 2
+
+#define EPT_TX(x) (1 << (((x) & 0xffff) + 16))
+#define EPT_RX(x) (1 << ((x) & 0xffff))
+
#define CTRL_TXE (1 << 23)
#define CTRL_TXR (1 << 22)
#define CTRL_RXE (1 << 7)
#define CTRL_RXR (1 << 6)
#define CTRL_TXT_BULK (2 << 18)
#define CTRL_RXT_BULK (2 << 2)
- u32 epctrl[16]; /* 0x1c0 */
-};
struct ci_ep {
struct usb_ep ep;
--
cgit
From a022c1e13c01d88edd3436c291630d4b8c642787 Mon Sep 17 00:00:00 2001
From: Stephen Warren
Date: Thu, 24 Apr 2014 17:52:40 -0600
Subject: usb: ums: use only 1 buffer for CI_UDC
ci_udc.c allocates only a single buffer for each endpoint, which
ci_ep_alloc_request() returns as a hard-coded value rather than
dynamically allocating. Consequently, storage_common.c must limit
itself to using a single buffer at a time. Add a special case
to the definition of FSG_NUM_BUFFERS for this.
Another option would be to fix ci_ep_alloc_request() to dynamically
allocate the buffers like some/all(?) other device mode drivers do.
However, I don't think that ci_ep_queue() supports queueing up
multiple buffers either yet, and I'm not familiar enough with the
controller yet to implement that. As such, any attempt to use multiple
buffers simply results in data corruption and other errors.
Signed-off-by: Stephen Warren
---
drivers/usb/gadget/storage_common.c | 4 ++++
1 file changed, 4 insertions(+)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 02803df23c..74300746b9 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -311,7 +311,11 @@ static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */
/* Number of buffers we will use. 2 is enough for double-buffering */
+#ifndef CONFIG_CI_UDC
#define FSG_NUM_BUFFERS 2
+#else
+#define FSG_NUM_BUFFERS 1 /* ci_udc only allows 1 req per ep at present */
+#endif
/* Default size of buffer length. */
#define FSG_BUFLEN ((u32)16384)
--
cgit
From 2fc5dab2ed19b6e15ba0726905b6311793397806 Mon Sep 17 00:00:00 2001
From: Stephen Warren
Date: Mon, 28 Apr 2014 15:42:00 -0600
Subject: usb: gadget: allow ci_udc to build with new gadget framework
Allow ci_udc.o to be built when using the new(?) USB gadget framework,
as enabled by CONFIG_USB_GADGET.
Note that this duplicates the Makefile entry for ci_udc.o, since it's
also included inside #ifdef CONFIG_USB_ETHER. I'm not sure what that
define means; perhaps an old style of Ethernet-specific USB gadget
implementation?
I wonder if the line that this patch adds shouldn't be outside all of
the ifdefs, so it stands on its own, similar to how e.g. epautoconf.o
is shared between the two?
Signed-off-by: Stephen Warren
---
drivers/usb/gadget/Makefile | 1 +
1 file changed, 1 insertion(+)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 804a2bd412..896c8d407e 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -13,6 +13,7 @@ ifdef CONFIG_USB_GADGET
obj-$(CONFIG_USB_GADGET_ATMEL_USBA) += atmel_usba_udc.o
obj-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
obj-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o
+obj-$(CONFIG_CI_UDC) += ci_udc.o
obj-$(CONFIG_THOR_FUNCTION) += f_thor.o
obj-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
obj-$(CONFIG_DFU_FUNCTION) += f_dfu.o
--
cgit
From 75504e9592745021006cb8905b5ff5a51d9d1cb3 Mon Sep 17 00:00:00 2001
From: Mateusz Zalega
Date: Wed, 30 Apr 2014 13:07:48 +0200
Subject: usb: dfu: fix boards wo USB cable detection
Former usb_cable_connected() patch broke compilation of boards which do
not support this feature.
I've renamed usb_cable_connected() to g_dnl_usb_cable_connected() and added
its default implementation to gadget downloader driver code. There's
only one driver of this kind and it's unlikely there'll be another, so
there's no point in keeping it in /common.
Previously this function was declared in usb.h. I've moved it, since
it's more appropriate to keep it in g_dnl.h - usb.h seems to be intended
for USB host implementation.
Existing code, confronted with default -EOPNOTSUPP return value,
continues as if the cable was connected.
CONFIG_USB_CABLE_CHECK was removed.
Change-Id: Ib9198621adee2811b391c64512f14646cefd0369
Signed-off-by: Mateusz Zalega
Acked-by: Marek Vasut
Acked-by: Lukasz Majewski
---
drivers/usb/gadget/f_mass_storage.c | 8 ++++----
drivers/usb/gadget/g_dnl.c | 5 +++++
2 files changed, 9 insertions(+), 4 deletions(-)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index f896169743..4fae5cd3b1 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -243,7 +243,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -680,11 +680,11 @@ static int sleep_thread(struct fsg_common *common)
/* Handle CTRL+C */
if (ctrlc())
return -EPIPE;
-#ifdef CONFIG_USB_CABLE_CHECK
+
/* Check cable connection */
- if (!usb_cable_connected())
+ if (!g_dnl_board_usb_cable_connected())
return -EIO;
-#endif
+
k = 0;
}
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index dd95afe86a..973d7378b5 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -152,6 +152,11 @@ __weak int g_dnl_get_board_bcd_device_number(int gcnum)
return gcnum;
}
+__weak int g_dnl_board_usb_cable_connected(void)
+{
+ return -EOPNOTSUPP;
+}
+
static int g_dnl_get_bcd_device_number(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
--
cgit
From c4d0e856047f2689278ffea63a562c4f22a35ee3 Mon Sep 17 00:00:00 2001
From: Mateusz Zalega
Date: Mon, 28 Apr 2014 21:13:28 +0200
Subject: USB: gadget: added a saner gadget downloader registration API
Preprocessor definitions and hardcoded implementation selection in
g_dnl core were replaced by a linker list made of (usb_function_name,
bind_callback) pairs.
Signed-off-by: Mateusz Zalega
Acked-by: Lukasz Majewski
Acked-by: Marek Vasut
---
drivers/usb/gadget/f_dfu.c | 3 ++
drivers/usb/gadget/f_mass_storage.c | 3 ++
drivers/usb/gadget/f_thor.c | 2 ++
drivers/usb/gadget/g_dnl.c | 64 ++++++++++++++++---------------------
4 files changed, 36 insertions(+), 36 deletions(-)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index de75ff1339..1b1e1793d9 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -24,6 +24,7 @@
#include
#include
+#include
#include "f_dfu.h"
struct f_dfu {
@@ -817,3 +818,5 @@ int dfu_add(struct usb_configuration *c)
return dfu_bind_config(c);
}
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_dfu, dfu_add);
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 4fae5cd3b1..6374bb953a 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -255,6 +255,7 @@
#include
#include
#include
+#include
/*------------------------------------------------------------------------*/
@@ -2778,3 +2779,5 @@ int fsg_init(struct ums *ums_dev)
return 0;
}
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_ums, fsg_add);
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index ba47945007..feef9e4619 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -1004,3 +1004,5 @@ int thor_add(struct usb_configuration *c)
debug("%s:\n", __func__);
return thor_func_init(c);
}
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_thor, thor_add);
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 973d7378b5..743bae535a 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -41,7 +41,6 @@
#define DRIVER_VERSION "usb_dnl 2.0"
-static const char shortname[] = "usb_dnl_";
static const char product[] = "USB download gadget";
static char g_dnl_serial[MAX_STRING_SERIAL];
static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER;
@@ -96,29 +95,36 @@ static int g_dnl_unbind(struct usb_composite_dev *cdev)
free(cdev->config);
cdev->config = NULL;
debug("%s: calling usb_gadget_disconnect for "
- "controller '%s'\n", shortname, gadget->name);
+ "controller '%s'\n", __func__, gadget->name);
usb_gadget_disconnect(gadget);
return 0;
}
+static inline struct g_dnl_bind_callback *g_dnl_bind_callback_first(void)
+{
+ return ll_entry_start(struct g_dnl_bind_callback,
+ g_dnl_bind_callbacks);
+}
+
+static inline struct g_dnl_bind_callback *g_dnl_bind_callback_end(void)
+{
+ return ll_entry_end(struct g_dnl_bind_callback,
+ g_dnl_bind_callbacks);
+}
+
static int g_dnl_do_config(struct usb_configuration *c)
{
const char *s = c->cdev->driver->name;
- int ret = -1;
+ struct g_dnl_bind_callback *callback = g_dnl_bind_callback_first();
debug("%s: configuration: 0x%p composite dev: 0x%p\n",
__func__, c, c->cdev);
- printf("GADGET DRIVER: %s\n", s);
- if (!strcmp(s, "usb_dnl_dfu"))
- ret = dfu_add(c);
- else if (!strcmp(s, "usb_dnl_ums"))
- ret = fsg_add(c);
- else if (!strcmp(s, "usb_dnl_thor"))
- ret = thor_add(c);
-
- return ret;
+ for (; callback != g_dnl_bind_callback_end(); callback++)
+ if (!strcmp(s, callback->usb_function_name))
+ return callback->fptr(c);
+ return -ENODEV;
}
static int g_dnl_config_register(struct usb_composite_dev *cdev)
@@ -208,12 +214,12 @@ static int g_dnl_bind(struct usb_composite_dev *cdev)
device_desc.bcdDevice = cpu_to_le16(gcnum);
else {
debug("%s: controller '%s' not recognized\n",
- shortname, gadget->name);
+ __func__, gadget->name);
device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
}
debug("%s: calling usb_gadget_connect for "
- "controller '%s'\n", shortname, gadget->name);
+ "controller '%s'\n", __func__, gadget->name);
usb_gadget_connect(gadget);
return 0;
@@ -232,36 +238,22 @@ static struct usb_composite_driver g_dnl_driver = {
.unbind = g_dnl_unbind,
};
-int g_dnl_register(const char *type)
+/*
+ * NOTICE:
+ * Registering via USB function name won't be necessary after rewriting
+ * g_dnl to support multiple USB functions.
+ */
+int g_dnl_register(const char *name)
{
- /* The largest function name is 4 */
- static char name[sizeof(shortname) + 4];
- int ret;
-
- if (!strcmp(type, "dfu")) {
- strcpy(name, shortname);
- strcat(name, type);
- } else if (!strcmp(type, "ums")) {
- strcpy(name, shortname);
- strcat(name, type);
- } else if (!strcmp(type, "thor")) {
- strcpy(name, shortname);
- strcat(name, type);
- } else {
- printf("%s: unknown command: %s\n", __func__, type);
- return -EINVAL;
- }
+ int ret = usb_composite_register(&g_dnl_driver);
+ debug("%s: g_dnl_driver.name = %s\n", __func__, name);
g_dnl_driver.name = name;
- debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name);
- ret = usb_composite_register(&g_dnl_driver);
-
if (ret) {
printf("%s: failed!, error: %d\n", __func__, ret);
return ret;
}
-
return 0;
}
--
cgit
From 25fbf96b24fd3fe0a5252c374b445be32f42b0c8 Mon Sep 17 00:00:00 2001
From: Stephen Warren
Date: Thu, 1 May 2014 15:45:16 -0600
Subject: USB: gadget: save driver name before registering it
g_dnl_register() currently first attempts to register a composite
driver by name, and then saves the driver name once it's registered.
Internally to the registration code, g_dnl_do_config() is called and
attempts to compare the composite device's name with the list of known
device names. This fails since the composite device's name has not yet
been stored. This means that the first time "ums 0 0" is run, it fails,
but subsequent attempts succeed.
Re-order the name-saving and registration code to solve this.
Fixes: e5b834e07f51 ("USB: gadget: added a saner gadget downloader registration API")
Signed-off-by: Stephen Warren
---
drivers/usb/gadget/g_dnl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
(limited to 'drivers/usb/gadget')
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 743bae535a..25611acd60 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -245,11 +245,12 @@ static struct usb_composite_driver g_dnl_driver = {
*/
int g_dnl_register(const char *name)
{
- int ret = usb_composite_register(&g_dnl_driver);
+ int ret;
debug("%s: g_dnl_driver.name = %s\n", __func__, name);
g_dnl_driver.name = name;
+ ret = usb_composite_register(&g_dnl_driver);
if (ret) {
printf("%s: failed!, error: %d\n", __func__, ret);
return ret;
--
cgit