summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2011-07-07 17:39:32 +0200
committerHarald Welte <laforge@gnumonks.org>2011-07-07 17:39:32 +0200
commitfe88b83e80df8be0351ff38ee6a77b855b0cd0a9 (patch)
tree93f6d6c0bd11d9f3a92a5daef69db1df6eb4ca44 /firmware
parent30cb576ca5ed5281e997333fd522440faa595565 (diff)
dfu: fix EP0 IN trasnfers that are even multiple of 8
We have to send a ZLP at the end of such transfers, otherwise the host will time out at the end of the transfer. This resulted in multi-second delays for recognizing the SIMtrace hardware by the USB host.
Diffstat (limited to 'firmware')
-rw-r--r--firmware/src/dfu/dfu.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/firmware/src/dfu/dfu.c b/firmware/src/dfu/dfu.c
index f740800..8425c28 100644
--- a/firmware/src/dfu/dfu.c
+++ b/firmware/src/dfu/dfu.c
@@ -86,18 +86,20 @@ static void __dfufunc udp_init(void)
AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, OPENPCD_PIO_UDP_PUPv4);
}
+static void __dfufunc udp_ep0_send_zlp(void);
+
/* Send Data through the control endpoint */
static void __dfufunc udp_ep0_send_data(const char *pData, u_int32_t length)
{
AT91PS_UDP pUdp = AT91C_BASE_UDP;
- u_int32_t cpt = 0;
+ u_int32_t cpt = 0, len_remain = length;
AT91_REG csr;
DEBUGE("send_data: %u bytes ", length);
do {
- cpt = MIN(length, 8);
- length -= cpt;
+ cpt = MIN(len_remain, 8);
+ len_remain -= cpt;
while (cpt--)
pUdp->UDP_FDR[0] = *pData++;
@@ -119,12 +121,20 @@ static void __dfufunc udp_ep0_send_data(const char *pData, u_int32_t length)
}
} while (!(csr & AT91C_UDP_TXCOMP));
- } while (length);
+ } while (len_remain);
if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) ;
}
+
+ if ((length % 8) == 0) {
+ /* if the length is a multiple of the EP size, we need
+ * to send another ZLP (zero-length packet) to tell the
+ * host the transfer has completed. */
+ DEBUGE("set_txpktrdy_zlp ");
+ udp_ep0_send_zlp();
+ }
}
static void udp_ep0_recv_clean(void)
personal git repositories of Harald Welte. Your mileage may vary