USB host: Modify the transfer() and asynch() methods so that the actual size of the transfer is returned. Unverified on initial commit.

This commit is contained in:
Gregory Nutt
2015-05-05 13:14:22 -06:00
parent fdaabe2341
commit 47a112974d
13 changed files with 734 additions and 527 deletions
+4
View File
@@ -10306,3 +10306,7 @@
(2015-05-03). (2015-05-03).
* fs/vfs/fs_poll.c: Fix resource leak and memory corruption on poll * fs/vfs/fs_poll.c: Fix resource leak and memory corruption on poll
failure. From Jussi Kivilinna (2015-05-04). failure. From Jussi Kivilinna (2015-05-04).
* All USB host drivers in arch/ and all USB class drivers in drivers/usbhost:
Modify the transfer() and asynch() methods so that the actual size of
the transfer is returned. Unverified on initial commit (2015-05-05).
File diff suppressed because it is too large Load Diff
+4 -6
View File
@@ -961,16 +961,14 @@ config USBHOST_IOBUFSIZE
Size of one end-user I/O buffer. This can be zero if the application Size of one end-user I/O buffer. This can be zero if the application
can guarantee that all end-user I/O buffers reside in AHB SRAM. can guarantee that all end-user I/O buffers reside in AHB SRAM.
config LPC17_USBHOST_NASYNCH config LPC17_USBHOST_NPREALLOC
int "Number asynch transfers" int "Max concurrent transfers"
default 8 if USBHOST_HUB default 8 if USBHOST_HUB
default 4 if !USBHOST_HUB default 4 if !USBHOST_HUB
depends on USBHOST_ASYNCH
---help--- ---help---
This number represents a number of pre-allocated structures to support This number represents a number of pre-allocated structures to support
asynchronous IN data transfers. This number effective determines that concurrent data transfers. This number limits that number of concurrent
number of concurrent asynchronous IN endpoint transfer that can be asynchronous IN endpoint transfer that can be supported.
supported.
config USBHOST_BULK_DISABLE config USBHOST_BULK_DISABLE
bool "Disable bulk EPs" bool "Disable bulk EPs"
File diff suppressed because it is too large Load Diff
+19 -14
View File
@@ -545,7 +545,7 @@ static int lpc31_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer); FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer);
static int lpc31_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, static int lpc31_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer); FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer);
static int lpc31_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t lpc31_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static int lpc31_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static int lpc31_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
@@ -2630,6 +2630,7 @@ static inline int lpc31_asynch_setup(struct lpc31_rhport_s *rhport,
static void lpc31_asynch_completion(struct lpc31_epinfo_s *epinfo) static void lpc31_asynch_completion(struct lpc31_epinfo_s *epinfo)
{ {
usbhost_asynch_t callback; usbhost_asynch_t callback;
ssize_t nbytes;
void *arg; void *arg;
int result; int result;
@@ -2641,15 +2642,23 @@ static void lpc31_asynch_completion(struct lpc31_epinfo_s *epinfo)
callback = epinfo->callback; callback = epinfo->callback;
arg = epinfo->arg; arg = epinfo->arg;
result = epinfo->result; result = epinfo->result;
nbytes = epinfo->xfrd;
epinfo->callback = NULL; epinfo->callback = NULL;
epinfo->arg = NULL; epinfo->arg = NULL;
epinfo->result = OK; epinfo->result = OK;
epinfo->iocwait = false; epinfo->iocwait = false;
/* Then perform the callback */ /* Then perform the callback. Provide the number of bytes successfully
* transferred or the negated errno value in the event of a failure.
*/
callback(arg, result); if (result < 0)
{
nbytes = (ssize_t)result;
}
callback(arg, nbytes);
} }
#endif #endif
@@ -4273,8 +4282,9 @@ static int lpc31_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* buflen - The length of the data to be sent or received. * buflen - The length of the data to be sent or received.
* *
* Returned Values: * Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is * On success, a non-negative value is returned that indicates the number
* returned indicating the nature of the failure: * of bytes successfully transferred. On a failure, a negated errno value is
* returned that indicates the nature of the failure:
* *
* EAGAIN - If devices NAKs the transfer (or NYET or other error where * EAGAIN - If devices NAKs the transfer (or NYET or other error where
* it may be appropriate to restart the entire transaction). * it may be appropriate to restart the entire transaction).
@@ -4288,7 +4298,7 @@ static int lpc31_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* *
*******************************************************************************/ *******************************************************************************/
static int lpc31_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t lpc31_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen) FAR uint8_t *buffer, size_t buflen)
{ {
struct lpc31_rhport_s *rhport = (struct lpc31_rhport_s *)drvr; struct lpc31_rhport_s *rhport = (struct lpc31_rhport_s *)drvr;
@@ -4347,13 +4357,13 @@ static int lpc31_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
nbytes = lpc31_transfer_wait(epinfo); nbytes = lpc31_transfer_wait(epinfo);
lpc31_givesem(&g_ehci.exclsem); lpc31_givesem(&g_ehci.exclsem);
return nbytes >= 0 ? OK : (int)nbytes; return nbytes;
errout_with_iocwait: errout_with_iocwait:
epinfo->iocwait = false; epinfo->iocwait = false;
errout_with_sem: errout_with_sem:
lpc31_givesem(&g_ehci.exclsem); lpc31_givesem(&g_ehci.exclsem);
return ret; return (ssize_t)ret;
} }
/******************************************************************************* /*******************************************************************************
@@ -4676,12 +4686,7 @@ static int lpc31_connect(FAR struct usbhost_driver_s *drvr,
static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr, static void lpc31_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport) FAR struct usbhost_hubport_s *hport)
{ {
struct lpc31_rhport_s *rhport = (struct lpc31_rhport_s *)drvr; DEBUGASSERT(hport != NULL);
DEBUGASSERT(rhport != NULL && hport != NULL);
/* Unbind the class */
/* REVISIT: Is there more that needs to be done? */
hport->devclass = NULL; hport->devclass = NULL;
} }
+20 -15
View File
@@ -421,7 +421,7 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer); FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer);
static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer); FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer);
static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static int sam_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static int sam_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
@@ -2448,6 +2448,7 @@ static inline int sam_asynch_setup(struct sam_rhport_s *rhport,
static void sam_asynch_completion(struct sam_epinfo_s *epinfo) static void sam_asynch_completion(struct sam_epinfo_s *epinfo)
{ {
usbhost_asynch_t callback; usbhost_asynch_t callback;
ssize_t nbytes;
void *arg; void *arg;
int result; int result;
@@ -2459,15 +2460,23 @@ static void sam_asynch_completion(struct sam_epinfo_s *epinfo)
callback = epinfo->callback; callback = epinfo->callback;
arg = epinfo->arg; arg = epinfo->arg;
result = epinfo->result; result = epinfo->result;
nbytes = epinfo->xfrd;
epinfo->callback = NULL; epinfo->callback = NULL;
epinfo->arg = NULL; epinfo->arg = NULL;
epinfo->result = OK; epinfo->result = OK;
epinfo->iocwait = false; epinfo->iocwait = false;
/* Then perform the callback */ /* Then perform the callback. Provide the number of bytes successfully
* transferred or the negated errno value in the event of a failure.
*/
callback(arg, result); if (result < 0)
{
nbytes = (ssize_t)result;
}
callback(arg, nbytes);
} }
#endif #endif
@@ -4099,8 +4108,9 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* buflen - The length of the data to be sent or received. * buflen - The length of the data to be sent or received.
* *
* Returned Values: * Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is * On success, a non-negative value is returned that indicates the number
* returned indicating the nature of the failure: * of bytes successfully transferred. On a failure, a negated errno value is
* returned that indicates the nature of the failure:
* *
* EAGAIN - If devices NAKs the transfer (or NYET or other error where * EAGAIN - If devices NAKs the transfer (or NYET or other error where
* it may be appropriate to restart the entire transaction). * it may be appropriate to restart the entire transaction).
@@ -4114,7 +4124,7 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* *
*******************************************************************************/ *******************************************************************************/
static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen) FAR uint8_t *buffer, size_t buflen)
{ {
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
@@ -4174,13 +4184,13 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
nbytes = sam_transfer_wait(epinfo); nbytes = sam_transfer_wait(epinfo);
sam_givesem(&g_ehci.exclsem); sam_givesem(&g_ehci.exclsem);
return nbytes >= 0 ? OK : (int)nbytes; return nbytes;
errout_with_iocwait: errout_with_iocwait:
epinfo->iocwait = false; epinfo->iocwait = false;
errout_with_sem: errout_with_sem:
sam_givesem(&g_ehci.exclsem); sam_givesem(&g_ehci.exclsem);
return ret; return (ssize_t)ret;
} }
/******************************************************************************* /*******************************************************************************
@@ -4503,13 +4513,8 @@ static int sam_connect(FAR struct usbhost_driver_s *drvr,
static void sam_disconnect(FAR struct usbhost_driver_s *drvr, static void sam_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport) FAR struct usbhost_hubport_s *hport)
{ {
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; DEBUGASSERT(hport != NULL);
DEBUGASSERT(rhport != NULL && hport != NULL); hport->devclass = NULL;
/* Unbind the class */
/* REVISIT: Is there more that needs to be done? */
rhport->hport.hport.devclass = NULL;
} }
/******************************************************************************* /*******************************************************************************
+32 -14
View File
@@ -224,9 +224,10 @@ struct sam_eplist_s
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
usbhost_asynch_t callback; /* Transfer complete callback */ usbhost_asynch_t callback; /* Transfer complete callback */
void *arg; /* Argument that accompanies the callback */ void *arg; /* Argument that accompanies the callback */
uint8_t *buffer; /* Buffer being transferred */
uint16_t buflen; /* Length of the buffer */ uint16_t buflen; /* Length of the buffer */
#endif #endif
uint8_t *buffer; /* Buffer being transferred */
uint16_t xfrd; /* Number of bytes completed in the last transfer */
struct sam_ed_s *ed; /* Endpoint descriptor (ED) */ struct sam_ed_s *ed; /* Endpoint descriptor (ED) */
struct sam_gtd_s *tail; /* Tail transfer descriptor (TD) */ struct sam_gtd_s *tail; /* Tail transfer descriptor (TD) */
}; };
@@ -444,7 +445,7 @@ static int sam_ctrlout(struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
static int sam_transfer_common(struct sam_rhport_s *rhport, static int sam_transfer_common(struct sam_rhport_s *rhport,
struct sam_eplist_s *eplist, struct sam_eplist_s *eplist,
uint8_t *buffer, size_t buflen); uint8_t *buffer, size_t buflen);
static int sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
uint8_t *buffer, size_t buflen); uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static void sam_asynch_completion(struct sam_eplist_s *eplist); static void sam_asynch_completion(struct sam_eplist_s *eplist);
@@ -2077,6 +2078,8 @@ static void sam_wdh_bottomhalf(void)
struct sam_gtd_s *td; struct sam_gtd_s *td;
struct sam_gtd_s *next; struct sam_gtd_s *next;
struct sam_ed_s *ed; struct sam_ed_s *ed;
uintptr_t paddr;
uintptr_t tmp;
/* The host controller just wrote the one finished TDs into the HCCA /* The host controller just wrote the one finished TDs into the HCCA
* done head. This may include multiple packets that were transferred * done head. This may include multiple packets that were transferred
@@ -2147,6 +2150,16 @@ static void sam_wdh_bottomhalf(void)
} }
#endif #endif
/* Determine the size of the transfer by subtracting the current buffer
* pointer (CBP) from the initial buffer pointer (on packet receipt only).
*/
paddr = sam_physramaddr((uintptr_t)eplist->buffer);
tmp = (uintptr_t)td->hw.cbp - paddr;
DEBUGASSERT(tmp < UINT16_MAX);
eplist->xfrd = (uint16_t)tmp;
/* Return the TD to the free list */ /* Return the TD to the free list */
next = (struct sam_gtd_s *)sam_virtramaddr(td->hw.nexttd); next = (struct sam_gtd_s *)sam_virtramaddr(td->hw.nexttd);
@@ -3253,12 +3266,13 @@ static int sam_transfer_common(struct sam_rhport_s *rhport,
* *
*******************************************************************************/ *******************************************************************************/
static int sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
uint8_t *buffer, size_t buflen) uint8_t *buffer, size_t buflen)
{ {
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr; struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
struct sam_eplist_s *eplist = (struct sam_eplist_s *)ep; struct sam_eplist_s *eplist = (struct sam_eplist_s *)ep;
struct sam_ed_s *ed; struct sam_ed_s *ed;
ssize_t nbytes;
bool in; bool in;
int ret; int ret;
@@ -3339,21 +3353,24 @@ static int sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
(uintptr_t)buffer + buflen); (uintptr_t)buffer + buflen);
} }
ret = OK; nbytes = eplist->xfrd;
DEBUGASSERT(nbytes >=0 && nbytes <= buflen);
sam_givesem(&g_ohci.exclsem);
return nbytes;
} }
else
{ /* A transfer error occurred */
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, RHPORT(rhport),
ed->tdstatus); usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, RHPORT(rhport), ed->tdstatus);
ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO; ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO;
}
errout: errout:
/* Make sure that there is no outstanding request on this endpoint */ /* Make sure that there is no outstanding request on this endpoint */
eplist->wdhwait = false; eplist->wdhwait = false;
sam_givesem(&g_ohci.exclsem); sam_givesem(&g_ohci.exclsem);
return ret; return (ssize_t)ret;
} }
/******************************************************************************* /*******************************************************************************
@@ -3382,7 +3399,7 @@ static void sam_asynch_completion(struct sam_eplist_s *eplist)
struct sam_ed_s *ed; struct sam_ed_s *ed;
usbhost_asynch_t callback; usbhost_asynch_t callback;
void *arg; void *arg;
int result; ssize_t nbytes;
DEBUGASSERT(eplist->ed && eplist->tail && eplist->callback != NULL && DEBUGASSERT(eplist->ed && eplist->tail && eplist->callback != NULL &&
eplist->buffer != NULL && eplist->buflen > 0); eplist->buffer != NULL && eplist->buflen > 0);
@@ -3407,12 +3424,13 @@ static void sam_asynch_completion(struct sam_eplist_s *eplist)
arch_invalidate_dcache(buffaddr, buffaddr + eplist->buflen); arch_invalidate_dcache(buffaddr, buffaddr + eplist->buflen);
} }
result = OK; nbytes = eplist->xfrd;
DEBUGASSERT(nbytes >= 0 && nbytes <= eplist->buflen);
} }
else else
{ {
usbhost_trace1(OHCI_TRACE1_BADTDSTATUS, ed->tdstatus); usbhost_trace1(OHCI_TRACE1_BADTDSTATUS, ed->tdstatus);
result = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO; nbytes = (ed->tdstatus == TD_CC_STALL) ? -EPERM : -EIO;
} }
/* Extract the callback information before freeing the buffer */ /* Extract the callback information before freeing the buffer */
@@ -3430,7 +3448,7 @@ static void sam_asynch_completion(struct sam_eplist_s *eplist)
/* Then perform the callback */ /* Then perform the callback */
callback(arg, result); callback(arg, nbytes);
} }
#endif #endif
+96 -67
View File
@@ -220,7 +220,8 @@ struct stm32_chan_s
bool in; /* True: IN endpoint */ bool in; /* True: IN endpoint */
volatile bool waiter; /* True: Thread is waiting for a channel event */ volatile bool waiter; /* True: Thread is waiting for a channel event */
uint16_t maxpacket; /* Max packet size */ uint16_t maxpacket; /* Max packet size */
volatile uint16_t buflen; /* Buffer length (remaining) */ uint16_t buflen; /* Buffer length (at start of transfer) */
volatile uint16_t xfrd; /* Bytes transferred (at end of transfer) */
volatile uint16_t inflight; /* Number of Tx bytes "in-flight" */ volatile uint16_t inflight; /* Number of Tx bytes "in-flight" */
FAR uint8_t *buffer; /* Transfer buffer pointer */ FAR uint8_t *buffer; /* Transfer buffer pointer */
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
@@ -356,7 +357,7 @@ static int stm32_ctrl_recvdata(FAR struct stm32_usbhost_s *priv,
FAR struct stm32_ctrlinfo_s *ep0, FAR struct stm32_ctrlinfo_s *ep0,
FAR uint8_t *buffer, unsigned int buflen); FAR uint8_t *buffer, unsigned int buflen);
static int stm32_in_setup(FAR struct stm32_usbhost_s *priv, int chidx); static int stm32_in_setup(FAR struct stm32_usbhost_s *priv, int chidx);
static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static void stm32_in_next(FAR struct stm32_usbhost_s *priv, static void stm32_in_next(FAR struct stm32_usbhost_s *priv,
@@ -366,7 +367,7 @@ static int stm32_in_asynch(FAR struct stm32_usbhost_s *priv, int chidx,
usbhost_asynch_t callback, FAR void *arg); usbhost_asynch_t callback, FAR void *arg);
#endif #endif
static int stm32_out_setup(FAR struct stm32_usbhost_s *priv, int chidx); static int stm32_out_setup(FAR struct stm32_usbhost_s *priv, int chidx);
static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx, static ssize_t stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static void stm32_out_next(FAR struct stm32_usbhost_s *priv, static void stm32_out_next(FAR struct stm32_usbhost_s *priv,
@@ -441,7 +442,7 @@ static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR const struct usb_ctrlreq_s *req, FAR const struct usb_ctrlreq_s *req,
FAR const uint8_t *buffer); FAR const uint8_t *buffer);
static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static int stm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static int stm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
@@ -1104,7 +1105,7 @@ static int stm32_chan_wait(FAR struct stm32_usbhost_s *priv,
ret = sem_wait(&chan->waitsem); ret = sem_wait(&chan->waitsem);
/* sem_wait should succeeed. But it is possible that we could be /* sem_wait should succeed. But it is possible that we could be
* awakened by a signal too. * awakened by a signal too.
*/ */
@@ -1402,6 +1403,7 @@ static void stm32_transfer_start(FAR struct stm32_usbhost_s *priv, int chidx)
chan->result = EBUSY; chan->result = EBUSY;
chan->inflight = 0; chan->inflight = 0;
chan->xfrd = 0;
priv->chidx = chidx; priv->chidx = chidx;
/* Compute the expected number of packets associated to the transfer. /* Compute the expected number of packets associated to the transfer.
@@ -1611,11 +1613,12 @@ static int stm32_ctrl_sendsetup(FAR struct stm32_usbhost_s *priv,
chan->pid = OTGFS_PID_SETUP; chan->pid = OTGFS_PID_SETUP;
chan->buffer = (FAR uint8_t *)req; chan->buffer = (FAR uint8_t *)req;
chan->buflen = USB_SIZEOF_CTRLREQ; chan->buflen = USB_SIZEOF_CTRLREQ;
chan->xfrd = 0;
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGFS_TRACE1_DEVDISCONN, 0); usbhost_trace1(OTGFS_TRACE1_DEVDISCONN, 0);
return ret; return ret;
@@ -1677,6 +1680,7 @@ static int stm32_ctrl_senddata(FAR struct stm32_usbhost_s *priv,
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
/* Set the DATA PID */ /* Set the DATA PID */
@@ -1694,7 +1698,7 @@ static int stm32_ctrl_senddata(FAR struct stm32_usbhost_s *priv,
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGFS_TRACE1_DEVDISCONN, 0); usbhost_trace1(OTGFS_TRACE1_DEVDISCONN, 0);
return ret; return ret;
@@ -1730,11 +1734,12 @@ static int stm32_ctrl_recvdata(FAR struct stm32_usbhost_s *priv,
chan->pid = OTGFS_PID_DATA1; chan->pid = OTGFS_PID_DATA1;
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGFS_TRACE1_DEVDISCONN, 0); usbhost_trace1(OTGFS_TRACE1_DEVDISCONN, 0);
return ret; return ret;
@@ -1818,13 +1823,13 @@ static int stm32_in_setup(FAR struct stm32_usbhost_s *priv, int chidx)
* *
*******************************************************************************/ *******************************************************************************/
static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen) FAR uint8_t *buffer, size_t buflen)
{ {
FAR struct stm32_chan_s *chan; FAR struct stm32_chan_s *chan;
uint32_t start; uint32_t start;
uint32_t elapsed; uint32_t elapsed;
int ret = OK; int ret;
/* Loop until the transfer completes (i.e., buflen is decremented to zero) /* Loop until the transfer completes (i.e., buflen is decremented to zero)
* or a fatal error occurs (any error other than a simple NAK) * or a fatal error occurs (any error other than a simple NAK)
@@ -1833,17 +1838,18 @@ static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
chan = &priv->chan[chidx]; chan = &priv->chan[chidx];
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
start = clock_systimer(); start = clock_systimer();
while (chan->buflen > 0) while (chan->xfrd < chan->buflen)
{ {
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGFS_TRACE1_DEVDISCONN, 0); usbhost_trace1(OTGFS_TRACE1_DEVDISCONN, 0);
return ret; return (ssize_t)ret;
} }
/* Set up for the transfer based on the direction and the endpoint type */ /* Set up for the transfer based on the direction and the endpoint type */
@@ -1852,7 +1858,7 @@ static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
if (ret < 0) if (ret < 0)
{ {
udbg("ERROR: stm32_in_setup failed: %d\n", ret); udbg("ERROR: stm32_in_setup failed: %d\n", ret);
return ret; return (ssize_t)ret;
} }
/* Wait for the transfer to complete and get the result */ /* Wait for the transfer to complete and get the result */
@@ -1864,7 +1870,7 @@ static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
* cause use to return * cause use to return
*/ */
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGFS_TRACE1_TRNSFRFAILED,ret); usbhost_trace1(OTGFS_TRACE1_TRNSFRFAILED,ret);
@@ -1878,16 +1884,17 @@ static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
elapsed = clock_systimer() - start; elapsed = clock_systimer() - start;
if (ret != -EAGAIN || /* Not a NAK condition OR */ if (ret != -EAGAIN || /* Not a NAK condition OR */
elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */ elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */
chan->buflen != buflen) /* Data has been partially transferred */ chan->xfrd > 0) /* Data has been partially transferred */
{ {
/* Break out and return the error */ /* Break out and return the error */
break; udbg("ERROR: stm32_chan_wait failed: %d\n", ret);
return (ssize_t)ret;
} }
} }
} }
return ret; return (ssize_t)chan->xfrd;
} }
/******************************************************************************* /*******************************************************************************
@@ -1907,13 +1914,14 @@ static void stm32_in_next(FAR struct stm32_usbhost_s *priv,
{ {
usbhost_asynch_t callback; usbhost_asynch_t callback;
FAR void *arg; FAR void *arg;
ssize_t nbytes;
int result; int result;
int ret; int ret;
/* Is the full transfer complete? Did the last chunk transfer complete OK?*/ /* Is the full transfer complete? Did the last chunk transfer complete OK? */
result = chan->result; result = -(int)chan->result;
if (chan->buflen > 0 && result == OK) if (chan->xfrd < chan->buflen && result == OK)
{ {
/* Yes.. Set up for the next transfer based on the direction and the /* Yes.. Set up for the next transfer based on the direction and the
* endpoint type * endpoint type
@@ -1937,12 +1945,20 @@ static void stm32_in_next(FAR struct stm32_usbhost_s *priv,
callback = chan->callback; callback = chan->callback;
arg = chan->arg; arg = chan->arg;
nbytes = chan->xfrd;
chan->callback = NULL; chan->callback = NULL;
chan->arg = NULL; chan->arg = NULL;
chan->xfrd = 0;
/* Then perform the callback */ /* Then perform the callback */
callback(arg, chan->result); if (result < 0)
{
nbytes = (ssize_t)result;
}
callback(arg, nbytes);
} }
#endif #endif
@@ -1970,6 +1986,7 @@ static int stm32_in_asynch(FAR struct stm32_usbhost_s *priv, int chidx,
chan = &priv->chan[chidx]; chan = &priv->chan[chidx];
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
ret = stm32_chan_asynchsetup(priv, chan, callback, arg); ret = stm32_chan_asynchsetup(priv, chan, callback, arg);
if (ret < 0) if (ret < 0)
@@ -2065,14 +2082,15 @@ static int stm32_out_setup(FAR struct stm32_usbhost_s *priv, int chidx)
* *
*******************************************************************************/ *******************************************************************************/
static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx, static ssize_t stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen) FAR uint8_t *buffer, size_t buflen)
{ {
FAR struct stm32_chan_s *chan; FAR struct stm32_chan_s *chan;
uint32_t start; uint32_t start;
uint32_t elapsed; uint32_t elapsed;
size_t xfrlen; size_t xfrlen;
int ret = OK; ssize_t xfrd;
int ret;
/* Loop until the transfer completes (i.e., buflen is decremented to zero) /* Loop until the transfer completes (i.e., buflen is decremented to zero)
* or a fatal error occurs (any error other than a simple NAK) * or a fatal error occurs (any error other than a simple NAK)
@@ -2080,6 +2098,7 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
chan = &priv->chan[chidx]; chan = &priv->chan[chidx];
start = clock_systimer(); start = clock_systimer();
xfrd = 0;
while (buflen > 0) while (buflen > 0)
{ {
@@ -2091,14 +2110,15 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
xfrlen = MIN(chan->maxpacket, buflen); xfrlen = MIN(chan->maxpacket, buflen);
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = xfrlen; chan->buflen = xfrlen;
chan->xfrd = 0;
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGFS_TRACE1_DEVDISCONN,0); usbhost_trace1(OTGFS_TRACE1_DEVDISCONN,0);
return ret; return (ssize_t)ret;
} }
/* Set up for the transfer based on the direction and the endpoint type */ /* Set up for the transfer based on the direction and the endpoint type */
@@ -2107,7 +2127,7 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
if (ret < 0) if (ret < 0)
{ {
udbg("ERROR: stm32_out_setup failed: %d\n", ret); udbg("ERROR: stm32_out_setup failed: %d\n", ret);
return ret; return (ssize_t)ret;
} }
/* Wait for the transfer to complete and get the result */ /* Wait for the transfer to complete and get the result */
@@ -2116,7 +2136,7 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
/* Handle transfer failures */ /* Handle transfer failures */
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGFS_TRACE1_TRNSFRFAILED,ret); usbhost_trace1(OTGFS_TRACE1_TRNSFRFAILED,ret);
@@ -2130,11 +2150,12 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
elapsed = clock_systimer() - start; elapsed = clock_systimer() - start;
if (ret != -EAGAIN || /* Not a NAK condition OR */ if (ret != -EAGAIN || /* Not a NAK condition OR */
elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */ elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */
chan->buflen != xfrlen) /* Data has been partially transferred */ chan->xfrd != xfrlen) /* Data has been partially transferred */
{ {
/* Break out and return the error */ /* Break out and return the error */
break; udbg("ERROR: stm32_chan_wait failed: %d\n", ret);
return (ssize_t)ret;
} }
/* Is this flush really necessary? What does the hardware do with the /* Is this flush really necessary? What does the hardware do with the
@@ -2155,10 +2176,11 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
buffer += xfrlen; buffer += xfrlen;
buflen -= xfrlen; buflen -= xfrlen;
xfrd += chan->xfrd;
} }
} }
return ret; return xfrd;
} }
/******************************************************************************* /*******************************************************************************
@@ -2178,13 +2200,14 @@ static void stm32_out_next(FAR struct stm32_usbhost_s *priv,
{ {
usbhost_asynch_t callback; usbhost_asynch_t callback;
FAR void *arg; FAR void *arg;
ssize_t nbytes;
int result; int result;
int ret; int ret;
/* Is the full transfer complete? Did the last chunk transfer complete OK?*/ /* Is the full transfer complete? Did the last chunk transfer complete OK?*/
result = chan->result; result = -(int)chan->result;
if (chan->buflen > 0 && result == OK) if (chan->xfrd < chan->buflen && result == OK)
{ {
/* Yes.. Set up for the next transfer based on the direction and the /* Yes.. Set up for the next transfer based on the direction and the
* endpoint type * endpoint type
@@ -2208,12 +2231,20 @@ static void stm32_out_next(FAR struct stm32_usbhost_s *priv,
callback = chan->callback; callback = chan->callback;
arg = chan->arg; arg = chan->arg;
nbytes = chan->xfrd;
chan->callback = NULL; chan->callback = NULL;
chan->arg = NULL; chan->arg = NULL;
chan->xfrd = 0;
/* Then perform the callback */ /* Then perform the callback */
callback(arg, chan->result); if (result < 0)
{
nbytes = (ssize_t)result;
}
callback(arg, nbytes);
} }
#endif #endif
@@ -2241,6 +2272,7 @@ static int stm32_out_asynch(FAR struct stm32_usbhost_s *priv, int chidx,
chan = &priv->chan[chidx]; chan = &priv->chan[chidx];
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
ret = stm32_chan_asynchsetup(priv, chan, callback, arg); ret = stm32_chan_asynchsetup(priv, chan, callback, arg);
if (ret < 0) if (ret < 0)
@@ -2631,7 +2663,7 @@ static inline void stm32_gint_hcoutisr(FAR struct stm32_usbhost_s *priv,
*/ */
priv->chan[chidx].buffer += priv->chan[chidx].inflight; priv->chan[chidx].buffer += priv->chan[chidx].inflight;
priv->chan[chidx].buflen -= priv->chan[chidx].inflight; priv->chan[chidx].xfrd += priv->chan[chidx].inflight;
priv->chan[chidx].inflight = 0; priv->chan[chidx].inflight = 0;
/* Halt the channel -- the CHH interrupt is expected next */ /* Halt the channel -- the CHH interrupt is expected next */
@@ -2957,7 +2989,7 @@ static inline void stm32_gint_rxflvlisr(FAR struct stm32_usbhost_s *priv)
/* Manage multiple packet transfers */ /* Manage multiple packet transfers */
priv->chan[chidx].buffer += bcnt; priv->chan[chidx].buffer += bcnt;
priv->chan[chidx].buflen -= bcnt; priv->chan[chidx].xfrd += bcnt;
/* Check if more packets are expected */ /* Check if more packets are expected */
@@ -3015,15 +3047,15 @@ static inline void stm32_gint_nptxfeisr(FAR struct stm32_usbhost_s *priv)
*/ */
chan->buffer += chan->inflight; chan->buffer += chan->inflight;
chan->buflen -= chan->inflight; chan->xfrd += chan->inflight;
chan->inflight = 0; chan->inflight = 0;
/* If we have now transfered the entire buffer, then this transfer is /* If we have now transferred the entire buffer, then this transfer is
* complete (this case really should never happen because we disable * complete (this case really should never happen because we disable
* the NPTXFE interrupt on the final packet). * the NPTXFE interrupt on the final packet).
*/ */
if (chan->buflen <= 0) if (chan->xfrd >= chan->buflen)
{ {
/* Disable further Tx FIFO empty interrupts and bail. */ /* Disable further Tx FIFO empty interrupts and bail. */
@@ -3039,16 +3071,15 @@ static inline void stm32_gint_nptxfeisr(FAR struct stm32_usbhost_s *priv)
avail = ((regval & OTGFS_HNPTXSTS_NPTXFSAV_MASK) >> OTGFS_HNPTXSTS_NPTXFSAV_SHIFT) << 2; avail = ((regval & OTGFS_HNPTXSTS_NPTXFSAV_MASK) >> OTGFS_HNPTXSTS_NPTXFSAV_SHIFT) << 2;
/* Get the size to put in the Tx FIFO now */
wrsize = chan->buflen - chan->xfrd;
/* Get minimal size packet that can be sent. Something is seriously /* Get minimal size packet that can be sent. Something is seriously
* configured wrong if one packet will not fit into the empty Tx FIFO. * configured wrong if one packet will not fit into the empty Tx FIFO.
*/ */
DEBUGASSERT(chan->buflen > 0 && DEBUGASSERT(wrsize > 0 && avail >= MIN(wrsize, chan->maxpacket));
avail >= MIN(chan->buflen, chan->maxpacket));
/* Get the size to put in the Tx FIFO now */
wrsize = chan->buflen;
if (wrsize > avail) if (wrsize > avail)
{ {
/* Clip the write size to the number of full, max sized packets /* Clip the write size to the number of full, max sized packets
@@ -3070,8 +3101,8 @@ static inline void stm32_gint_nptxfeisr(FAR struct stm32_usbhost_s *priv)
/* Write the next group of packets into the Tx FIFO */ /* Write the next group of packets into the Tx FIFO */
ullvdbg("HNPTXSTS: %08x chidx: %d avail: %d buflen: %d wrsize: %d\n", ullvdbg("HNPTXSTS: %08x chidx: %d avail: %d buflen: %d xfrd: %d wrsize: %d\n",
regval, chidx, avail, chan->buflen, wrsize); regval, chidx, avail, chan->buflen, chan->xfrd, wrsize);
stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize); stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize);
} }
@@ -3104,7 +3135,7 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv)
*/ */
chan->buffer += chan->inflight; chan->buffer += chan->inflight;
chan->buflen -= chan->inflight; chan->xfrd += chan->inflight;
chan->inflight = 0; chan->inflight = 0;
/* If we have now transfered the entire buffer, then this transfer is /* If we have now transfered the entire buffer, then this transfer is
@@ -3112,7 +3143,7 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv)
* the PTXFE interrupt on the final packet). * the PTXFE interrupt on the final packet).
*/ */
if (chan->buflen <= 0) if (chan->xfrd >= chan->buflen)
{ {
/* Disable further Tx FIFO empty interrupts and bail. */ /* Disable further Tx FIFO empty interrupts and bail. */
@@ -3128,16 +3159,15 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv)
avail = ((regval & OTGFS_HPTXSTS_PTXFSAVL_MASK) >> OTGFS_HPTXSTS_PTXFSAVL_SHIFT) << 2; avail = ((regval & OTGFS_HPTXSTS_PTXFSAVL_MASK) >> OTGFS_HPTXSTS_PTXFSAVL_SHIFT) << 2;
/* Get the size to put in the Tx FIFO now */
wrsize = chan->buflen - chan->xfrd;
/* Get minimal size packet that can be sent. Something is seriously /* Get minimal size packet that can be sent. Something is seriously
* configured wrong if one packet will not fit into the empty Tx FIFO. * configured wrong if one packet will not fit into the empty Tx FIFO.
*/ */
DEBUGASSERT(chan->buflen > 0 && DEBUGASSERT(wrsize && avail >= MIN(wrsize, chan->maxpacket));
avail >= MIN(chan->buflen, chan->maxpacket));
/* Get the size to put in the Tx FIFO now */
wrsize = chan->buflen;
if (wrsize > avail) if (wrsize > avail)
{ {
/* Clip the write size to the number of full, max sized packets /* Clip the write size to the number of full, max sized packets
@@ -3159,8 +3189,8 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv)
/* Write the next group of packets into the Tx FIFO */ /* Write the next group of packets into the Tx FIFO */
ullvdbg("HPTXSTS: %08x chidx: %d avail: %d buflen: %d wrsize: %d\n", ullvdbg("HPTXSTS: %08x chidx: %d avail: %d buflen: %d xfrd: %d wrsize: %d\n",
regval, chidx, avail, chan->buflen, wrsize); regval, chidx, avail, chan->buflen, chan->xfrd, wrsize);
stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize); stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize);
} }
@@ -4462,8 +4492,9 @@ static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* buflen - The length of the data to be sent or received. * buflen - The length of the data to be sent or received.
* *
* Returned Values: * Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is * On success, a non-negative value is returned that indicates the number
* returned indicating the nature of the failure: * of bytes successfully transferred. On a failure, a negated errno value is
* returned that indicates the nature of the failure:
* *
* EAGAIN - If devices NAKs the transfer (or NYET or other error where * EAGAIN - If devices NAKs the transfer (or NYET or other error where
* it may be appropriate to restart the entire transaction). * it may be appropriate to restart the entire transaction).
@@ -4477,12 +4508,12 @@ static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* *
*******************************************************************************/ *******************************************************************************/
static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen) FAR uint8_t *buffer, size_t buflen)
{ {
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
unsigned int chidx = (unsigned int)ep; unsigned int chidx = (unsigned int)ep;
int ret; ssize_t nbytes;
uvdbg("chidx: %d buflen: %d\n", (unsigned int)ep, buflen); uvdbg("chidx: %d buflen: %d\n", (unsigned int)ep, buflen);
@@ -4496,15 +4527,15 @@ static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
if (priv->chan[chidx].in) if (priv->chan[chidx].in)
{ {
ret = stm32_in_transfer(priv, chidx, buffer, buflen); nbytes = stm32_in_transfer(priv, chidx, buffer, buflen);
} }
else else
{ {
ret = stm32_out_transfer(priv, chidx, buffer, buflen); nbytes = stm32_out_transfer(priv, chidx, buffer, buflen);
} }
stm32_givesem(&priv->exclsem); stm32_givesem(&priv->exclsem);
return ret; return nbytes;
} }
/******************************************************************************* /*******************************************************************************
@@ -4700,9 +4731,7 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr, static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport) FAR struct usbhost_hubport_s *hport)
{ {
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; DEBUGASSERT(hport != NULL);
DEBUGASSERT(priv != NULL && hport != NULL);
hport->devclass = NULL; hport->devclass = NULL;
} }
+96 -67
View File
@@ -220,7 +220,8 @@ struct stm32_chan_s
bool in; /* True: IN endpoint */ bool in; /* True: IN endpoint */
volatile bool waiter; /* True: Thread is waiting for a channel event */ volatile bool waiter; /* True: Thread is waiting for a channel event */
uint16_t maxpacket; /* Max packet size */ uint16_t maxpacket; /* Max packet size */
volatile uint16_t buflen; /* Buffer length (remaining) */ uint16_t buflen; /* Buffer length (at start of transfer) */
volatile uint16_t xfrd; /* Bytes transferred (at end of transfer) */
volatile uint16_t inflight; /* Number of Tx bytes "in-flight" */ volatile uint16_t inflight; /* Number of Tx bytes "in-flight" */
FAR uint8_t *buffer; /* Transfer buffer pointer */ FAR uint8_t *buffer; /* Transfer buffer pointer */
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
@@ -356,7 +357,7 @@ static int stm32_ctrl_recvdata(FAR struct stm32_usbhost_s *priv,
FAR struct stm32_ctrlinfo_s *ep0, FAR struct stm32_ctrlinfo_s *ep0,
FAR uint8_t *buffer, unsigned int buflen); FAR uint8_t *buffer, unsigned int buflen);
static int stm32_in_setup(FAR struct stm32_usbhost_s *priv, int chidx); static int stm32_in_setup(FAR struct stm32_usbhost_s *priv, int chidx);
static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static void stm32_in_next(FAR struct stm32_usbhost_s *priv, static void stm32_in_next(FAR struct stm32_usbhost_s *priv,
@@ -366,7 +367,7 @@ static int stm32_in_asynch(FAR struct stm32_usbhost_s *priv, int chidx,
usbhost_asynch_t callback, FAR void *arg); usbhost_asynch_t callback, FAR void *arg);
#endif #endif
static int stm32_out_setup(FAR struct stm32_usbhost_s *priv, int chidx); static int stm32_out_setup(FAR struct stm32_usbhost_s *priv, int chidx);
static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx, static ssize_t stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static void stm32_out_next(FAR struct stm32_usbhost_s *priv, static void stm32_out_next(FAR struct stm32_usbhost_s *priv,
@@ -441,7 +442,7 @@ static int stm32_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0, static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
FAR const struct usb_ctrlreq_s *req, FAR const struct usb_ctrlreq_s *req,
FAR const uint8_t *buffer); FAR const uint8_t *buffer);
static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
#ifdef CONFIG_USBHOST_ASYNCH #ifdef CONFIG_USBHOST_ASYNCH
static int stm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static int stm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
@@ -1104,7 +1105,7 @@ static int stm32_chan_wait(FAR struct stm32_usbhost_s *priv,
ret = sem_wait(&chan->waitsem); ret = sem_wait(&chan->waitsem);
/* sem_wait should succeeed. But it is possible that we could be /* sem_wait should succeed. But it is possible that we could be
* awakened by a signal too. * awakened by a signal too.
*/ */
@@ -1402,6 +1403,7 @@ static void stm32_transfer_start(FAR struct stm32_usbhost_s *priv, int chidx)
chan->result = EBUSY; chan->result = EBUSY;
chan->inflight = 0; chan->inflight = 0;
chan->xfrd = 0;
priv->chidx = chidx; priv->chidx = chidx;
/* Compute the expected number of packets associated to the transfer. /* Compute the expected number of packets associated to the transfer.
@@ -1611,11 +1613,12 @@ static int stm32_ctrl_sendsetup(FAR struct stm32_usbhost_s *priv,
chan->pid = OTGHS_PID_SETUP; chan->pid = OTGHS_PID_SETUP;
chan->buffer = (FAR uint8_t *)req; chan->buffer = (FAR uint8_t *)req;
chan->buflen = USB_SIZEOF_CTRLREQ; chan->buflen = USB_SIZEOF_CTRLREQ;
chan->xfrd = 0;
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGHS_TRACE1_DEVDISCONN, 0); usbhost_trace1(OTGHS_TRACE1_DEVDISCONN, 0);
return ret; return ret;
@@ -1677,6 +1680,7 @@ static int stm32_ctrl_senddata(FAR struct stm32_usbhost_s *priv,
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
/* Set the DATA PID */ /* Set the DATA PID */
@@ -1694,7 +1698,7 @@ static int stm32_ctrl_senddata(FAR struct stm32_usbhost_s *priv,
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGHS_TRACE1_DEVDISCONN, 0); usbhost_trace1(OTGHS_TRACE1_DEVDISCONN, 0);
return ret; return ret;
@@ -1730,11 +1734,12 @@ static int stm32_ctrl_recvdata(FAR struct stm32_usbhost_s *priv,
chan->pid = OTGHS_PID_DATA1; chan->pid = OTGHS_PID_DATA1;
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGHS_TRACE1_DEVDISCONN, 0); usbhost_trace1(OTGHS_TRACE1_DEVDISCONN, 0);
return ret; return ret;
@@ -1818,13 +1823,13 @@ static int stm32_in_setup(FAR struct stm32_usbhost_s *priv, int chidx)
* *
*******************************************************************************/ *******************************************************************************/
static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx, static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen) FAR uint8_t *buffer, size_t buflen)
{ {
FAR struct stm32_chan_s *chan; FAR struct stm32_chan_s *chan;
uint32_t start; uint32_t start;
uint32_t elapsed; uint32_t elapsed;
int ret = OK; int ret;
/* Loop until the transfer completes (i.e., buflen is decremented to zero) /* Loop until the transfer completes (i.e., buflen is decremented to zero)
* or a fatal error occurs (any error other than a simple NAK) * or a fatal error occurs (any error other than a simple NAK)
@@ -1833,17 +1838,18 @@ static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
chan = &priv->chan[chidx]; chan = &priv->chan[chidx];
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
start = clock_systimer(); start = clock_systimer();
while (chan->buflen > 0) while (chan->xfrd < chan->buflen)
{ {
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGHS_TRACE1_DEVDISCONN, 0); usbhost_trace1(OTGHS_TRACE1_DEVDISCONN, 0);
return ret; return (ssize_t)ret;
} }
/* Set up for the transfer based on the direction and the endpoint type */ /* Set up for the transfer based on the direction and the endpoint type */
@@ -1852,7 +1858,7 @@ static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
if (ret < 0) if (ret < 0)
{ {
udbg("ERROR: stm32_in_setup failed: %d\n", ret); udbg("ERROR: stm32_in_setup failed: %d\n", ret);
return ret; return (ssize_t)ret;
} }
/* Wait for the transfer to complete and get the result */ /* Wait for the transfer to complete and get the result */
@@ -1864,7 +1870,7 @@ static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
* cause use to return * cause use to return
*/ */
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGHS_TRACE1_TRNSFRFAILED,ret); usbhost_trace1(OTGHS_TRACE1_TRNSFRFAILED,ret);
@@ -1878,16 +1884,17 @@ static int stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
elapsed = clock_systimer() - start; elapsed = clock_systimer() - start;
if (ret != -EAGAIN || /* Not a NAK condition OR */ if (ret != -EAGAIN || /* Not a NAK condition OR */
elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */ elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */
chan->buflen != buflen) /* Data has been partially transferred */ chan->xfrd > 0) /* Data has been partially transferred */
{ {
/* Break out and return the error */ /* Break out and return the error */
break; udbg("ERROR: stm32_chan_wait failed: %d\n", ret);
return (ssize_t)ret;
} }
} }
} }
return ret; return (ssize_t)chan->xfrd;
} }
/******************************************************************************* /*******************************************************************************
@@ -1907,13 +1914,14 @@ static void stm32_in_next(FAR struct stm32_usbhost_s *priv,
{ {
usbhost_asynch_t callback; usbhost_asynch_t callback;
FAR void *arg; FAR void *arg;
ssize_t nbytes;
int result; int result;
int ret; int ret;
/* Is the full transfer complete? Did the last chunk transfer complete OK?*/ /* Is the full transfer complete? Did the last chunk transfer complete OK? */
result = chan->result; result = -(int)chan->result;
if (chan->buflen > 0 && result == OK) if (chan->xfrd < chan->buflen && result == OK)
{ {
/* Yes.. Set up for the next transfer based on the direction and the /* Yes.. Set up for the next transfer based on the direction and the
* endpoint type * endpoint type
@@ -1937,12 +1945,20 @@ static void stm32_in_next(FAR struct stm32_usbhost_s *priv,
callback = chan->callback; callback = chan->callback;
arg = chan->arg; arg = chan->arg;
nbytes = chan->xfrd;
chan->callback = NULL; chan->callback = NULL;
chan->arg = NULL; chan->arg = NULL;
chan->xfrd = 0;
/* Then perform the callback */ /* Then perform the callback */
callback(arg, chan->result); if (result < 0)
{
nbytes = (ssize_t)result;
}
callback(arg, nbytes);
} }
#endif #endif
@@ -1970,6 +1986,7 @@ static int stm32_in_asynch(FAR struct stm32_usbhost_s *priv, int chidx,
chan = &priv->chan[chidx]; chan = &priv->chan[chidx];
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
ret = stm32_chan_asynchsetup(priv, chan, callback, arg); ret = stm32_chan_asynchsetup(priv, chan, callback, arg);
if (ret < 0) if (ret < 0)
@@ -2065,14 +2082,15 @@ static int stm32_out_setup(FAR struct stm32_usbhost_s *priv, int chidx)
* *
*******************************************************************************/ *******************************************************************************/
static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx, static ssize_t stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
FAR uint8_t *buffer, size_t buflen) FAR uint8_t *buffer, size_t buflen)
{ {
FAR struct stm32_chan_s *chan; FAR struct stm32_chan_s *chan;
uint32_t start; uint32_t start;
uint32_t elapsed; uint32_t elapsed;
size_t xfrlen; size_t xfrlen;
int ret = OK; ssize_t xfrd;
int ret;
/* Loop until the transfer completes (i.e., buflen is decremented to zero) /* Loop until the transfer completes (i.e., buflen is decremented to zero)
* or a fatal error occurs (any error other than a simple NAK) * or a fatal error occurs (any error other than a simple NAK)
@@ -2080,6 +2098,7 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
chan = &priv->chan[chidx]; chan = &priv->chan[chidx];
start = clock_systimer(); start = clock_systimer();
xfrd = 0;
while (buflen > 0) while (buflen > 0)
{ {
@@ -2091,14 +2110,15 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
xfrlen = MIN(chan->maxpacket, buflen); xfrlen = MIN(chan->maxpacket, buflen);
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = xfrlen; chan->buflen = xfrlen;
chan->xfrd = 0;
/* Set up for the wait BEFORE starting the transfer */ /* Set up for the wait BEFORE starting the transfer */
ret = stm32_chan_waitsetup(priv, chan); ret = stm32_chan_waitsetup(priv, chan);
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGHS_TRACE1_DEVDISCONN,0); usbhost_trace1(OTGHS_TRACE1_DEVDISCONN,0);
return ret; return (ssize_t)ret;
} }
/* Set up for the transfer based on the direction and the endpoint type */ /* Set up for the transfer based on the direction and the endpoint type */
@@ -2107,7 +2127,7 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
if (ret < 0) if (ret < 0)
{ {
udbg("ERROR: stm32_out_setup failed: %d\n", ret); udbg("ERROR: stm32_out_setup failed: %d\n", ret);
return ret; return (ssize_t)ret;
} }
/* Wait for the transfer to complete and get the result */ /* Wait for the transfer to complete and get the result */
@@ -2116,7 +2136,7 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
/* Handle transfer failures */ /* Handle transfer failures */
if (ret != OK) if (ret < 0)
{ {
usbhost_trace1(OTGHS_TRACE1_TRNSFRFAILED,ret); usbhost_trace1(OTGHS_TRACE1_TRNSFRFAILED,ret);
@@ -2130,11 +2150,12 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
elapsed = clock_systimer() - start; elapsed = clock_systimer() - start;
if (ret != -EAGAIN || /* Not a NAK condition OR */ if (ret != -EAGAIN || /* Not a NAK condition OR */
elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */ elapsed >= STM32_DATANAK_DELAY || /* Timeout has elapsed OR */
chan->buflen != xfrlen) /* Data has been partially transferred */ chan->xfrd != xfrlen) /* Data has been partially transferred */
{ {
/* Break out and return the error */ /* Break out and return the error */
break; udbg("ERROR: stm32_chan_wait failed: %d\n", ret);
return (ssize_t)ret;
} }
/* Is this flush really necessary? What does the hardware do with the /* Is this flush really necessary? What does the hardware do with the
@@ -2155,10 +2176,11 @@ static int stm32_out_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
buffer += xfrlen; buffer += xfrlen;
buflen -= xfrlen; buflen -= xfrlen;
xfrd += chan->xfrd;
} }
} }
return ret; return xfrd;
} }
/******************************************************************************* /*******************************************************************************
@@ -2178,13 +2200,14 @@ static void stm32_out_next(FAR struct stm32_usbhost_s *priv,
{ {
usbhost_asynch_t callback; usbhost_asynch_t callback;
FAR void *arg; FAR void *arg;
ssize_t nbytes;
int result; int result;
int ret; int ret;
/* Is the full transfer complete? Did the last chunk transfer complete OK?*/ /* Is the full transfer complete? Did the last chunk transfer complete OK?*/
result = chan->result; result = -(int)chan->result;
if (chan->buflen > 0 && result == OK) if (chan->xfrd < chan->buflen && result == OK)
{ {
/* Yes.. Set up for the next transfer based on the direction and the /* Yes.. Set up for the next transfer based on the direction and the
* endpoint type * endpoint type
@@ -2208,12 +2231,20 @@ static void stm32_out_next(FAR struct stm32_usbhost_s *priv,
callback = chan->callback; callback = chan->callback;
arg = chan->arg; arg = chan->arg;
nbytes = chan->xfrd;
chan->callback = NULL; chan->callback = NULL;
chan->arg = NULL; chan->arg = NULL;
chan->xfrd = 0;
/* Then perform the callback */ /* Then perform the callback */
callback(arg, chan->result); if (result < 0)
{
nbytes = (ssize_t)result;
}
callback(arg, nbytes);
} }
#endif #endif
@@ -2241,6 +2272,7 @@ static int stm32_out_asynch(FAR struct stm32_usbhost_s *priv, int chidx,
chan = &priv->chan[chidx]; chan = &priv->chan[chidx];
chan->buffer = buffer; chan->buffer = buffer;
chan->buflen = buflen; chan->buflen = buflen;
chan->xfrd = 0;
ret = stm32_chan_asynchsetup(priv, chan, callback, arg); ret = stm32_chan_asynchsetup(priv, chan, callback, arg);
if (ret < 0) if (ret < 0)
@@ -2631,7 +2663,7 @@ static inline void stm32_gint_hcoutisr(FAR struct stm32_usbhost_s *priv,
*/ */
priv->chan[chidx].buffer += priv->chan[chidx].inflight; priv->chan[chidx].buffer += priv->chan[chidx].inflight;
priv->chan[chidx].buflen -= priv->chan[chidx].inflight; priv->chan[chidx].xfrd += priv->chan[chidx].inflight;
priv->chan[chidx].inflight = 0; priv->chan[chidx].inflight = 0;
/* Halt the channel -- the CHH interrupt is expected next */ /* Halt the channel -- the CHH interrupt is expected next */
@@ -2957,7 +2989,7 @@ static inline void stm32_gint_rxflvlisr(FAR struct stm32_usbhost_s *priv)
/* Manage multiple packet transfers */ /* Manage multiple packet transfers */
priv->chan[chidx].buffer += bcnt; priv->chan[chidx].buffer += bcnt;
priv->chan[chidx].buflen -= bcnt; priv->chan[chidx].xfrd += bcnt;
/* Check if more packets are expected */ /* Check if more packets are expected */
@@ -3015,15 +3047,15 @@ static inline void stm32_gint_nptxfeisr(FAR struct stm32_usbhost_s *priv)
*/ */
chan->buffer += chan->inflight; chan->buffer += chan->inflight;
chan->buflen -= chan->inflight; chan->xfrd += chan->inflight;
chan->inflight = 0; chan->inflight = 0;
/* If we have now transfered the entire buffer, then this transfer is /* If we have now transferred the entire buffer, then this transfer is
* complete (this case really should never happen because we disable * complete (this case really should never happen because we disable
* the NPTXFE interrupt on the final packet). * the NPTXFE interrupt on the final packet).
*/ */
if (chan->buflen <= 0) if (chan->xfrd >= chan->buflen)
{ {
/* Disable further Tx FIFO empty interrupts and bail. */ /* Disable further Tx FIFO empty interrupts and bail. */
@@ -3039,16 +3071,15 @@ static inline void stm32_gint_nptxfeisr(FAR struct stm32_usbhost_s *priv)
avail = ((regval & OTGHS_HNPTXSTS_NPTXFSAV_MASK) >> OTGHS_HNPTXSTS_NPTXFSAV_SHIFT) << 2; avail = ((regval & OTGHS_HNPTXSTS_NPTXFSAV_MASK) >> OTGHS_HNPTXSTS_NPTXFSAV_SHIFT) << 2;
/* Get the size to put in the Tx FIFO now */
wrsize = chan->buflen - chan->xfrd;
/* Get minimal size packet that can be sent. Something is seriously /* Get minimal size packet that can be sent. Something is seriously
* configured wrong if one packet will not fit into the empty Tx FIFO. * configured wrong if one packet will not fit into the empty Tx FIFO.
*/ */
DEBUGASSERT(chan->buflen > 0 && DEBUGASSERT(wrsize > 0 && avail >= MIN(wrsize, chan->maxpacket));
avail >= MIN(chan->buflen, chan->maxpacket));
/* Get the size to put in the Tx FIFO now */
wrsize = chan->buflen;
if (wrsize > avail) if (wrsize > avail)
{ {
/* Clip the write size to the number of full, max sized packets /* Clip the write size to the number of full, max sized packets
@@ -3070,8 +3101,8 @@ static inline void stm32_gint_nptxfeisr(FAR struct stm32_usbhost_s *priv)
/* Write the next group of packets into the Tx FIFO */ /* Write the next group of packets into the Tx FIFO */
ullvdbg("HNPTXSTS: %08x chidx: %d avail: %d buflen: %d wrsize: %d\n", ullvdbg("HNPTXSTS: %08x chidx: %d avail: %d buflen: %d xfrd: %dwrsize: %d\n",
regval, chidx, avail, chan->buflen, wrsize); regval, chidx, avail, chan->buflen, chan->xfrd, wrsize);
stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize); stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize);
} }
@@ -3104,7 +3135,7 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv)
*/ */
chan->buffer += chan->inflight; chan->buffer += chan->inflight;
chan->buflen -= chan->inflight; chan->xfrd += chan->inflight;
chan->inflight = 0; chan->inflight = 0;
/* If we have now transfered the entire buffer, then this transfer is /* If we have now transfered the entire buffer, then this transfer is
@@ -3112,7 +3143,7 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv)
* the PTXFE interrupt on the final packet). * the PTXFE interrupt on the final packet).
*/ */
if (chan->buflen <= 0) if (chan->xfrd >= chan->buflen)
{ {
/* Disable further Tx FIFO empty interrupts and bail. */ /* Disable further Tx FIFO empty interrupts and bail. */
@@ -3128,16 +3159,15 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv)
avail = ((regval & OTGHS_HPTXSTS_PTXFSAVL_MASK) >> OTGHS_HPTXSTS_PTXFSAVL_SHIFT) << 2; avail = ((regval & OTGHS_HPTXSTS_PTXFSAVL_MASK) >> OTGHS_HPTXSTS_PTXFSAVL_SHIFT) << 2;
/* Get the size to put in the Tx FIFO now */
wrsize = chan->buflen - chan->xfrd;
/* Get minimal size packet that can be sent. Something is seriously /* Get minimal size packet that can be sent. Something is seriously
* configured wrong if one packet will not fit into the empty Tx FIFO. * configured wrong if one packet will not fit into the empty Tx FIFO.
*/ */
DEBUGASSERT(chan->buflen > 0 && DEBUGASSERT(wrsize > 0 && avail >= MIN(wrsize, chan->maxpacket));
avail >= MIN(chan->buflen, chan->maxpacket));
/* Get the size to put in the Tx FIFO now */
wrsize = chan->buflen;
if (wrsize > avail) if (wrsize > avail)
{ {
/* Clip the write size to the number of full, max sized packets /* Clip the write size to the number of full, max sized packets
@@ -3159,8 +3189,8 @@ static inline void stm32_gint_ptxfeisr(FAR struct stm32_usbhost_s *priv)
/* Write the next group of packets into the Tx FIFO */ /* Write the next group of packets into the Tx FIFO */
ullvdbg("HPTXSTS: %08x chidx: %d avail: %d buflen: %d wrsize: %d\n", ullvdbg("HPTXSTS: %08x chidx: %d avail: %d buflen: %d xfrd: %d wrsize: %d\n",
regval, chidx, avail, chan->buflen, wrsize); regval, chidx, avail, chan->buflen, chan->xfrd, wrsize);
stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize); stm32_gint_wrpacket(priv, chan->buffer, chidx, wrsize);
} }
@@ -4462,8 +4492,9 @@ static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* buflen - The length of the data to be sent or received. * buflen - The length of the data to be sent or received.
* *
* Returned Values: * Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is * On success, a non-negative value is returned that indicates the number
* returned indicating the nature of the failure: * of bytes successfully transferred. On a failure, a negated errno value is
* returned that indicates the nature of the failure:
* *
* EAGAIN - If devices NAKs the transfer (or NYET or other error where * EAGAIN - If devices NAKs the transfer (or NYET or other error where
* it may be appropriate to restart the entire transaction). * it may be appropriate to restart the entire transaction).
@@ -4477,12 +4508,12 @@ static int stm32_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* *
*******************************************************************************/ *******************************************************************************/
static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static ssize_t stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen) FAR uint8_t *buffer, size_t buflen)
{ {
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr;
unsigned int chidx = (unsigned int)ep; unsigned int chidx = (unsigned int)ep;
int ret; ssize_t nbytes;
uvdbg("chidx: %d buflen: %d\n", (unsigned int)ep, buflen); uvdbg("chidx: %d buflen: %d\n", (unsigned int)ep, buflen);
@@ -4496,15 +4527,15 @@ static int stm32_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
if (priv->chan[chidx].in) if (priv->chan[chidx].in)
{ {
ret = stm32_in_transfer(priv, chidx, buffer, buflen); nbytes = stm32_in_transfer(priv, chidx, buffer, buflen);
} }
else else
{ {
ret = stm32_out_transfer(priv, chidx, buffer, buflen); nbytes = stm32_out_transfer(priv, chidx, buffer, buflen);
} }
stm32_givesem(&priv->exclsem); stm32_givesem(&priv->exclsem);
return ret; return nbytes;
} }
/******************************************************************************* /*******************************************************************************
@@ -4700,9 +4731,7 @@ static int stm32_connect(FAR struct usbhost_driver_s *drvr,
static void stm32_disconnect(FAR struct usbhost_driver_s *drvr, static void stm32_disconnect(FAR struct usbhost_driver_s *drvr,
FAR struct usbhost_hubport_s *hport) FAR struct usbhost_hubport_s *hport)
{ {
FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; DEBUGASSERT(hport != NULL);
DEBUGASSERT(priv != NULL && hport != NULL);
hport->devclass = NULL; hport->devclass = NULL;
} }
+5 -3
View File
@@ -1052,6 +1052,7 @@ static int usbhost_mouse_poll(int argc, char *argv[])
unsigned int npolls = 0; unsigned int npolls = 0;
#endif #endif
unsigned int nerrors = 0; unsigned int nerrors = 0;
ssize_t nbytes;
int ret; int ret;
uvdbg("Started\n"); uvdbg("Started\n");
@@ -1084,14 +1085,14 @@ static int usbhost_mouse_poll(int argc, char *argv[])
* sends data. * sends data.
*/ */
ret = DRVR_TRANSFER(hport->drvr, priv->epin, nbytes = DRVR_TRANSFER(hport->drvr, priv->epin,
priv->tbuffer, priv->tbuflen); priv->tbuffer, priv->tbuflen);
/* Check for errors -- Bail if an excessive number of consecutive /* Check for errors -- Bail if an excessive number of consecutive
* errors are encountered. * errors are encountered.
*/ */
if (ret < 0) if (nbytes < 0)
{ {
/* If DRVR_TRANSFER() returns EAGAIN, that simply means that /* If DRVR_TRANSFER() returns EAGAIN, that simply means that
* the devices was not ready and has NAK'ed the transfer. That * the devices was not ready and has NAK'ed the transfer. That
@@ -1100,11 +1101,12 @@ static int usbhost_mouse_poll(int argc, char *argv[])
*/ */
udbg("ERROR: DRVR_TRANSFER returned: %d/%d\n", ret, nerrors); udbg("ERROR: DRVR_TRANSFER returned: %d/%d\n", ret, nerrors);
if (ret != -EAGAIN) if (nbytes != -EAGAIN)
{ {
if (++nerrors > 200) if (++nerrors > 200)
{ {
udbg("Too many errors... aborting: %d\n", nerrors); udbg("Too many errors... aborting: %d\n", nerrors);
ret = (int)nbytes;
break; break;
} }
} }
+10 -9
View File
@@ -86,7 +86,7 @@
# error Asynchronous transfer support is required (CONFIG_USBHOST_ASYNCH) # error Asynchronous transfer support is required (CONFIG_USBHOST_ASYNCH)
#endif #endif
#ifdef CONFIG_USBHOST_HUB_POLLMSEC #ifndef CONFIG_USBHOST_HUB_POLLMSEC
# define CONFIG_USBHOST_HUB_POLLMSEC 400 # define CONFIG_USBHOST_HUB_POLLMSEC 400
#endif #endif
@@ -166,7 +166,7 @@ static void usbhost_disconnect_event(FAR void *arg);
static inline uint16_t usbhost_getle16(const uint8_t *val); static inline uint16_t usbhost_getle16(const uint8_t *val);
static void usbhost_putle16(uint8_t *dest, uint16_t val); static void usbhost_putle16(uint8_t *dest, uint16_t val);
static void usbhost_callback(FAR void *arg, int result); static void usbhost_callback(FAR void *arg, ssize_t nbytes);
/* struct usbhost_registry_s methods */ /* struct usbhost_registry_s methods */
@@ -1149,7 +1149,8 @@ static void usbhost_putle16(uint8_t *dest, uint16_t val)
* *
* Input Parameters: * Input Parameters:
* arg - The argument provided with the asynchronous I/O was setup * arg - The argument provided with the asynchronous I/O was setup
* result - The result of the transfer * nbytes - The number of bytes actually transferred (or a negated errno
* value;
* *
* Returned Values: * Returned Values:
* None * None
@@ -1159,7 +1160,7 @@ static void usbhost_putle16(uint8_t *dest, uint16_t val)
* *
****************************************************************************/ ****************************************************************************/
static void usbhost_callback(FAR void *arg, int result) static void usbhost_callback(FAR void *arg, ssize_t nbytes)
{ {
FAR struct usbhost_class_s *hubclass; FAR struct usbhost_class_s *hubclass;
FAR struct usbhost_hubpriv_s *priv; FAR struct usbhost_hubpriv_s *priv;
@@ -1173,22 +1174,22 @@ static void usbhost_callback(FAR void *arg, int result)
* transfer will pend until data is available (OHCI and EHCI). On lower * transfer will pend until data is available (OHCI and EHCI). On lower
* end host controllers (like STM32 and EFM32), the transfer will fail * end host controllers (like STM32 and EFM32), the transfer will fail
* immediately when the device NAKs the first attempted interrupt IN * immediately when the device NAKs the first attempted interrupt IN
* transfer (with result == EAGAIN). In that case (or in the case of * transfer (with nbytes == -EAGAIN). In that case (or in the case of
* other errors), we must fall back to polling. * other errors), we must fall back to polling.
*/ */
if (result != OK) if (nbytes < 0)
{ {
/* This debug output is good to know, but really a nuisance for /* This debug output is good to know, but really a nuisance for
* those configurations where we have to fall back to polling. * those configurations where we have to fall back to polling.
* FIX: Don't output the message is the result is EAGAIN. * FIX: Don't output the message is the result is -EAGAIN.
*/ */
#if defined(CONFIG_DEBUG_USB) && !defined(CONFIG_DEBUG_VERBOSE) #if defined(CONFIG_DEBUG_USB) && !defined(CONFIG_DEBUG_VERBOSE)
if (result != EAGAIN) if (nbytes != -EAGAIN)
#endif #endif
{ {
ulldbg("ERROR: Transfer failed: %d\n", result); ulldbg("ERROR: Transfer failed: %d\n", (int)nbytes);
} }
/* Indicate there there is nothing to do. So when the work is /* Indicate there there is nothing to do. So when the work is
+56 -58
View File
@@ -711,7 +711,7 @@ static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv)
{ {
FAR struct usbhost_hubport_s *hport; FAR struct usbhost_hubport_s *hport;
FAR struct usbmsc_cbw_s *cbw; FAR struct usbmsc_cbw_s *cbw;
int result; ssize_t nbytes;
DEBUGASSERT(priv->usbclass.hport); DEBUGASSERT(priv->usbclass.hport);
hport = priv->usbclass.hport; hport = priv->usbclass.hport;
@@ -728,28 +728,28 @@ static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv)
/* Construct and send the CBW */ /* Construct and send the CBW */
usbhost_testunitreadycbw(cbw); usbhost_testunitreadycbw(cbw);
result = DRVR_TRANSFER(hport->drvr, priv->bulkout, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
(uint8_t*)cbw, USBMSC_CBW_SIZEOF); (uint8_t*)cbw, USBMSC_CBW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
/* Receive the CSW */ /* Receive the CSW */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, USBMSC_CSW_SIZEOF); priv->tbuffer, USBMSC_CSW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer); usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer);
} }
} }
return result; return nbytes < 0 ? (int)nbytes : OK;
} }
static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv) static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv)
{ {
FAR struct usbhost_hubport_s *hport; FAR struct usbhost_hubport_s *hport;
FAR struct usbmsc_cbw_s *cbw; FAR struct usbmsc_cbw_s *cbw;
int result; ssize_t nbytes;
DEBUGASSERT(priv->usbclass.hport); DEBUGASSERT(priv->usbclass.hport);
hport = priv->usbclass.hport; hport = priv->usbclass.hport;
@@ -766,28 +766,28 @@ static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv)
/* Construct and send the CBW */ /* Construct and send the CBW */
usbhost_requestsensecbw(cbw); usbhost_requestsensecbw(cbw);
result = DRVR_TRANSFER(hport->drvr, priv->bulkout, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
(uint8_t*)cbw, USBMSC_CBW_SIZEOF); (uint8_t*)cbw, USBMSC_CBW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
/* Receive the sense data response */ /* Receive the sense data response */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF); priv->tbuffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
/* Receive the CSW */ /* Receive the CSW */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, USBMSC_CSW_SIZEOF); priv->tbuffer, USBMSC_CSW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer); usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer);
} }
} }
} }
return result; return nbytes < 0 ? (int)nbytes : OK;
} }
static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv) static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
@@ -795,7 +795,7 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
FAR struct usbhost_hubport_s *hport; FAR struct usbhost_hubport_s *hport;
FAR struct usbmsc_cbw_s *cbw; FAR struct usbmsc_cbw_s *cbw;
FAR struct scsiresp_readcapacity10_s *resp; FAR struct scsiresp_readcapacity10_s *resp;
int result; ssize_t nbytes;
DEBUGASSERT(priv->usbclass.hport); DEBUGASSERT(priv->usbclass.hport);
hport = priv->usbclass.hport; hport = priv->usbclass.hport;
@@ -812,15 +812,15 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
/* Construct and send the CBW */ /* Construct and send the CBW */
usbhost_readcapacitycbw(cbw); usbhost_readcapacitycbw(cbw);
result = DRVR_TRANSFER(hport->drvr, priv->bulkout, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
(uint8_t*)cbw, USBMSC_CBW_SIZEOF); (uint8_t*)cbw, USBMSC_CBW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
/* Receive the read capacity CBW IN response */ /* Receive the read capacity CBW IN response */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, SCSIRESP_READCAPACITY10_SIZEOF); priv->tbuffer, SCSIRESP_READCAPACITY10_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
/* Save the capacity information */ /* Save the capacity information */
@@ -830,23 +830,23 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
/* Receive the CSW */ /* Receive the CSW */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, USBMSC_CSW_SIZEOF); priv->tbuffer, USBMSC_CSW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer); usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer);
} }
} }
} }
return result; return nbytes < 0 ? (int)nbytes : OK;
} }
static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv) static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv)
{ {
FAR struct usbhost_hubport_s *hport; FAR struct usbhost_hubport_s *hport;
FAR struct usbmsc_cbw_s *cbw; FAR struct usbmsc_cbw_s *cbw;
int result; ssize_t nbytes;
DEBUGASSERT(priv->usbclass.hport); DEBUGASSERT(priv->usbclass.hport);
hport = priv->usbclass.hport; hport = priv->usbclass.hport;
@@ -863,35 +863,35 @@ static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv)
/* Construct and send the CBW */ /* Construct and send the CBW */
usbhost_inquirycbw(cbw); usbhost_inquirycbw(cbw);
result = DRVR_TRANSFER(hport->drvr, priv->bulkout, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
(uint8_t*)cbw, USBMSC_CBW_SIZEOF); (uint8_t*)cbw, USBMSC_CBW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
/* Receive the CBW IN response */ /* Receive the CBW IN response */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, SCSIRESP_INQUIRY_SIZEOF); priv->tbuffer, SCSIRESP_INQUIRY_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
#if 0 #if 0
FAR struct scsiresp_inquiry_s *resp; FAR struct scsiresp_inquiry_s *resp;
/* TODO: If USB debug is enabled, dump the response data here */ /* TODO: If USB debug is enabled, dump the response data here */
resp = (FAR struct scsiresp_inquiry_s *)priv->tbuffer; resp = (FAR struct scsiresp_inquiry_s *)priv->tbuffer;
#endif #endif
/* Receive the CSW */ /* Receive the CSW */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, USBMSC_CSW_SIZEOF); priv->tbuffer, USBMSC_CSW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer); usbhost_dumpcsw((FAR struct usbmsc_csw_s *)priv->tbuffer);
} }
} }
} }
return result; return nbytes < 0 ? (int)nbytes : OK;
} }
/**************************************************************************** /****************************************************************************
@@ -1977,8 +1977,7 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
{ {
FAR struct usbhost_state_s *priv; FAR struct usbhost_state_s *priv;
FAR struct usbhost_hubport_s *hport; FAR struct usbhost_hubport_s *hport;
ssize_t ret = 0; ssize_t nbytes = 0;
int result;
DEBUGASSERT(inode && inode->i_private); DEBUGASSERT(inode && inode->i_private);
priv = (FAR struct usbhost_state_s *)inode->i_private; priv = (FAR struct usbhost_state_s *)inode->i_private;
@@ -1998,7 +1997,7 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
* attempt to read from the device. * attempt to read from the device.
*/ */
ret = -ENODEV; nbytes = -ENODEV;
} }
else if (nsectors > 0) else if (nsectors > 0)
{ {
@@ -2008,7 +2007,7 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
/* Assume allocation failure */ /* Assume allocation failure */
ret = -ENOMEM; nbytes = -ENOMEM;
/* Initialize a CBW (re-using the allocated transfer buffer) */ /* Initialize a CBW (re-using the allocated transfer buffer) */
@@ -2023,26 +2022,26 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
{ {
/* Assume some device failure */ /* Assume some device failure */
ret = -ENODEV; nbytes = -ENODEV;
/* Construct and send the CBW */ /* Construct and send the CBW */
usbhost_readcbw(startsector, priv->blocksize, nsectors, cbw); usbhost_readcbw(startsector, priv->blocksize, nsectors, cbw);
result = DRVR_TRANSFER(hport->drvr, priv->bulkout, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
(uint8_t*)cbw, USBMSC_CBW_SIZEOF); (uint8_t*)cbw, USBMSC_CBW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
/* Receive the user data */ /* Receive the user data */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
buffer, priv->blocksize * nsectors); buffer, priv->blocksize * nsectors);
if (result == OK) if (nbytes >= 0)
{ {
/* Receive the CSW */ /* Receive the CSW */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, USBMSC_CSW_SIZEOF); priv->tbuffer, USBMSC_CSW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
FAR struct usbmsc_csw_s *csw; FAR struct usbmsc_csw_s *csw;
@@ -2051,12 +2050,12 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
csw = (FAR struct usbmsc_csw_s *)priv->tbuffer; csw = (FAR struct usbmsc_csw_s *)priv->tbuffer;
if (csw->status == 0) if (csw->status == 0)
{ {
ret = nsectors; nbytes = nsectors;
} }
} }
} }
} }
} while (result == -EAGAIN); } while (nbytes == -EAGAIN);
} }
usbhost_givesem(&priv->exclsem); usbhost_givesem(&priv->exclsem);
@@ -2064,7 +2063,7 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
/* On success, return the number of blocks read */ /* On success, return the number of blocks read */
return ret; return nbytes < 0 ? (int)nbytes : OK;
} }
/**************************************************************************** /****************************************************************************
@@ -2082,8 +2081,7 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
{ {
FAR struct usbhost_state_s *priv; FAR struct usbhost_state_s *priv;
FAR struct usbhost_hubport_s *hport; FAR struct usbhost_hubport_s *hport;
ssize_t ret; ssize_t nbytes;
int result;
uvdbg("sector: %d nsectors: %d sectorsize: %d\n"); uvdbg("sector: %d nsectors: %d sectorsize: %d\n");
@@ -2102,7 +2100,7 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
* attempt to write to the device. * attempt to write to the device.
*/ */
ret = -ENODEV; nbytes = -ENODEV;
} }
else else
{ {
@@ -2112,7 +2110,7 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
/* Assume allocation failure */ /* Assume allocation failure */
ret = -ENOMEM; nbytes = -ENOMEM;
/* Initialize a CBW (re-using the allocated transfer buffer) */ /* Initialize a CBW (re-using the allocated transfer buffer) */
@@ -2121,26 +2119,26 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
{ {
/* Assume some device failure */ /* Assume some device failure */
ret = -ENODEV; nbytes = -ENODEV;
/* Construct and send the CBW */ /* Construct and send the CBW */
usbhost_writecbw(startsector, priv->blocksize, nsectors, cbw); usbhost_writecbw(startsector, priv->blocksize, nsectors, cbw);
result = DRVR_TRANSFER(hport->drvr, priv->bulkout, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
(uint8_t*)cbw, USBMSC_CBW_SIZEOF); (uint8_t*)cbw, USBMSC_CBW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
/* Send the user data */ /* Send the user data */
result = DRVR_TRANSFER(hport->drvr, priv->bulkout, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
(uint8_t*)buffer, priv->blocksize * nsectors); (uint8_t*)buffer, priv->blocksize * nsectors);
if (result == OK) if (nbytes >= 0)
{ {
/* Receive the CSW */ /* Receive the CSW */
result = DRVR_TRANSFER(hport->drvr, priv->bulkin, nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
priv->tbuffer, USBMSC_CSW_SIZEOF); priv->tbuffer, USBMSC_CSW_SIZEOF);
if (result == OK) if (nbytes >= 0)
{ {
FAR struct usbmsc_csw_s *csw; FAR struct usbmsc_csw_s *csw;
@@ -2149,7 +2147,7 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
csw = (FAR struct usbmsc_csw_s *)priv->tbuffer; csw = (FAR struct usbmsc_csw_s *)priv->tbuffer;
if (csw->status == 0) if (csw->status == 0)
{ {
ret = nsectors; nbytes = nsectors;
} }
} }
} }
@@ -2161,7 +2159,7 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
/* On success, return the number of blocks written */ /* On success, return the number of blocks written */
return ret; return nbytes < 0 ? (int)nbytes : OK;
} }
#endif #endif
+10 -5
View File
@@ -490,8 +490,9 @@
* buflen - The length of the data to be sent or received. * buflen - The length of the data to be sent or received.
* *
* Returned Values: * Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is * On success, a non-negative value is returned that indicates the number
* returned indicating the nature of the failure: * of bytes successfully transferred. On a failure, a negated errno value is
* returned that indicates the nature of the failure:
* *
* EAGAIN - If devices NAKs the transfer (or NYET or other error where * EAGAIN - If devices NAKs the transfer (or NYET or other error where
* it may be appropriate to restart the entire transaction). * it may be appropriate to restart the entire transaction).
@@ -791,9 +792,13 @@ struct usbhost_connection_s
FAR struct usbhost_hubport_s *hport); FAR struct usbhost_hubport_s *hport);
}; };
/* Callback type used with asynchronous transfers */ /* Callback type used with asynchronous transfers. The result of the
* transfer is provided by the 'result' parameters. If >= 0, then 'result'
* is the number of bytes transfers. If < 0 then the transfer failed and
* result is a negated errno value that indicates the nature of the failure.
*/
typedef CODE void (*usbhost_asynch_t)(FAR void *arg, int result); typedef CODE void (*usbhost_asynch_t)(FAR void *arg, ssize_t result);
/* struct usbhost_driver_s provides access to the USB host driver from the /* struct usbhost_driver_s provides access to the USB host driver from the
* USB host class implementation. * USB host class implementation.
@@ -869,7 +874,7 @@ struct usbhost_driver_s
* transfer has completed. * transfer has completed.
*/ */
int (*transfer)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, ssize_t (*transfer)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen); FAR uint8_t *buffer, size_t buflen);
/* Process a request to handle a transfer asynchronously. This method /* Process a request to handle a transfer asynchronously. This method