mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 13:13:08 +08:00
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:
@@ -10306,3 +10306,7 @@
|
||||
(2015-05-03).
|
||||
* fs/vfs/fs_poll.c: Fix resource leak and memory corruption on poll
|
||||
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
@@ -961,16 +961,14 @@ config USBHOST_IOBUFSIZE
|
||||
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.
|
||||
|
||||
config LPC17_USBHOST_NASYNCH
|
||||
int "Number asynch transfers"
|
||||
config LPC17_USBHOST_NPREALLOC
|
||||
int "Max concurrent transfers"
|
||||
default 8 if USBHOST_HUB
|
||||
default 4 if !USBHOST_HUB
|
||||
depends on USBHOST_ASYNCH
|
||||
---help---
|
||||
This number represents a number of pre-allocated structures to support
|
||||
asynchronous IN data transfers. This number effective determines that
|
||||
number of concurrent asynchronous IN endpoint transfer that can be
|
||||
supported.
|
||||
concurrent data transfers. This number limits that number of concurrent
|
||||
asynchronous IN endpoint transfer that can be supported.
|
||||
|
||||
config USBHOST_BULK_DISABLE
|
||||
bool "Disable bulk EPs"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
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);
|
||||
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);
|
||||
#ifdef CONFIG_USBHOST_ASYNCH
|
||||
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)
|
||||
{
|
||||
usbhost_asynch_t callback;
|
||||
ssize_t nbytes;
|
||||
void *arg;
|
||||
int result;
|
||||
|
||||
@@ -2641,15 +2642,23 @@ static void lpc31_asynch_completion(struct lpc31_epinfo_s *epinfo)
|
||||
callback = epinfo->callback;
|
||||
arg = epinfo->arg;
|
||||
result = epinfo->result;
|
||||
nbytes = epinfo->xfrd;
|
||||
|
||||
epinfo->callback = NULL;
|
||||
epinfo->arg = NULL;
|
||||
epinfo->result = OK;
|
||||
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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
||||
* returned indicating the nature of the failure:
|
||||
* On success, a non-negative value is returned that indicates the number
|
||||
* 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
|
||||
* it may be appropriate to restart the entire transaction).
|
||||
@@ -4288,8 +4298,8 @@ 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,
|
||||
FAR uint8_t *buffer, size_t buflen)
|
||||
static ssize_t lpc31_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
FAR uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
struct lpc31_rhport_s *rhport = (struct lpc31_rhport_s *)drvr;
|
||||
struct lpc31_epinfo_s *epinfo = (struct lpc31_epinfo_s *)ep;
|
||||
@@ -4347,13 +4357,13 @@ static int lpc31_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
|
||||
nbytes = lpc31_transfer_wait(epinfo);
|
||||
lpc31_givesem(&g_ehci.exclsem);
|
||||
return nbytes >= 0 ? OK : (int)nbytes;
|
||||
return nbytes;
|
||||
|
||||
errout_with_iocwait:
|
||||
epinfo->iocwait = false;
|
||||
errout_with_sem:
|
||||
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,
|
||||
FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
struct lpc31_rhport_s *rhport = (struct lpc31_rhport_s *)drvr;
|
||||
DEBUGASSERT(rhport != NULL && hport != NULL);
|
||||
|
||||
/* Unbind the class */
|
||||
/* REVISIT: Is there more that needs to be done? */
|
||||
|
||||
DEBUGASSERT(hport != NULL);
|
||||
hport->devclass = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
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);
|
||||
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);
|
||||
#ifdef CONFIG_USBHOST_ASYNCH
|
||||
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)
|
||||
{
|
||||
usbhost_asynch_t callback;
|
||||
ssize_t nbytes;
|
||||
void *arg;
|
||||
int result;
|
||||
|
||||
@@ -2459,15 +2460,23 @@ static void sam_asynch_completion(struct sam_epinfo_s *epinfo)
|
||||
callback = epinfo->callback;
|
||||
arg = epinfo->arg;
|
||||
result = epinfo->result;
|
||||
nbytes = epinfo->xfrd;
|
||||
|
||||
epinfo->callback = NULL;
|
||||
epinfo->arg = NULL;
|
||||
epinfo->result = OK;
|
||||
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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
||||
* returned indicating the nature of the failure:
|
||||
* On success, a non-negative value is returned that indicates the number
|
||||
* 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
|
||||
* it may be appropriate to restart the entire transaction).
|
||||
@@ -4114,8 +4124,8 @@ 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,
|
||||
FAR uint8_t *buffer, size_t buflen)
|
||||
static ssize_t sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
FAR uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
|
||||
struct sam_epinfo_s *epinfo = (struct sam_epinfo_s *)ep;
|
||||
@@ -4174,13 +4184,13 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
|
||||
nbytes = sam_transfer_wait(epinfo);
|
||||
sam_givesem(&g_ehci.exclsem);
|
||||
return nbytes >= 0 ? OK : (int)nbytes;
|
||||
return nbytes;
|
||||
|
||||
errout_with_iocwait:
|
||||
epinfo->iocwait = false;
|
||||
errout_with_sem:
|
||||
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,
|
||||
FAR struct usbhost_hubport_s *hport)
|
||||
{
|
||||
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
|
||||
DEBUGASSERT(rhport != NULL && hport != NULL);
|
||||
|
||||
/* Unbind the class */
|
||||
/* REVISIT: Is there more that needs to be done? */
|
||||
|
||||
rhport->hport.hport.devclass = NULL;
|
||||
DEBUGASSERT(hport != NULL);
|
||||
hport->devclass = NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -219,14 +219,15 @@
|
||||
|
||||
struct sam_eplist_s
|
||||
{
|
||||
volatile bool wdhwait; /* TRUE: Thread is waiting for WDH interrupt */
|
||||
sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */
|
||||
volatile bool wdhwait; /* TRUE: Thread is waiting for WDH interrupt */
|
||||
sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */
|
||||
#ifdef CONFIG_USBHOST_ASYNCH
|
||||
usbhost_asynch_t callback; /* Transfer complete callback */
|
||||
void *arg; /* Argument that accompanies the callback */
|
||||
uint8_t *buffer; /* Buffer being transferred */
|
||||
uint16_t buflen; /* Length of the buffer */
|
||||
usbhost_asynch_t callback; /* Transfer complete callback */
|
||||
void *arg; /* Argument that accompanies the callback */
|
||||
uint16_t buflen; /* Length of the buffer */
|
||||
#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_gtd_s *tail; /* Tail transfer descriptor (TD) */
|
||||
};
|
||||
@@ -444,8 +445,8 @@ static int sam_ctrlout(struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
|
||||
static int sam_transfer_common(struct sam_rhport_s *rhport,
|
||||
struct sam_eplist_s *eplist,
|
||||
uint8_t *buffer, size_t buflen);
|
||||
static int sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
uint8_t *buffer, size_t buflen);
|
||||
static ssize_t sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
uint8_t *buffer, size_t buflen);
|
||||
#ifdef CONFIG_USBHOST_ASYNCH
|
||||
static void sam_asynch_completion(struct sam_eplist_s *eplist);
|
||||
static int sam_asynch(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
@@ -2077,6 +2078,8 @@ static void sam_wdh_bottomhalf(void)
|
||||
struct sam_gtd_s *td;
|
||||
struct sam_gtd_s *next;
|
||||
struct sam_ed_s *ed;
|
||||
uintptr_t paddr;
|
||||
uintptr_t tmp;
|
||||
|
||||
/* The host controller just wrote the one finished TDs into the HCCA
|
||||
* done head. This may include multiple packets that were transferred
|
||||
@@ -2147,6 +2150,16 @@ static void sam_wdh_bottomhalf(void)
|
||||
}
|
||||
#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 */
|
||||
|
||||
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,
|
||||
uint8_t *buffer, size_t buflen)
|
||||
static ssize_t sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
struct sam_rhport_s *rhport = (struct sam_rhport_s *)drvr;
|
||||
struct sam_eplist_s *eplist = (struct sam_eplist_s *)ep;
|
||||
struct sam_ed_s *ed;
|
||||
ssize_t nbytes;
|
||||
bool in;
|
||||
int ret;
|
||||
|
||||
@@ -3339,21 +3353,24 @@ static int sam_transfer(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
(uintptr_t)buffer + buflen);
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, RHPORT(rhport),
|
||||
ed->tdstatus);
|
||||
ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO;
|
||||
nbytes = eplist->xfrd;
|
||||
DEBUGASSERT(nbytes >=0 && nbytes <= buflen);
|
||||
|
||||
sam_givesem(&g_ohci.exclsem);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/* A transfer error occurred */
|
||||
|
||||
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, RHPORT(rhport), ed->tdstatus);
|
||||
ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO;
|
||||
|
||||
errout:
|
||||
/* Make sure that there is no outstanding request on this endpoint */
|
||||
|
||||
eplist->wdhwait = false;
|
||||
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;
|
||||
usbhost_asynch_t callback;
|
||||
void *arg;
|
||||
int result;
|
||||
ssize_t nbytes;
|
||||
|
||||
DEBUGASSERT(eplist->ed && eplist->tail && eplist->callback != NULL &&
|
||||
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);
|
||||
}
|
||||
|
||||
result = OK;
|
||||
nbytes = eplist->xfrd;
|
||||
DEBUGASSERT(nbytes >= 0 && nbytes <= eplist->buflen);
|
||||
}
|
||||
else
|
||||
{
|
||||
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 */
|
||||
@@ -3430,7 +3448,7 @@ static void sam_asynch_completion(struct sam_eplist_s *eplist)
|
||||
|
||||
/* Then perform the callback */
|
||||
|
||||
callback(arg, result);
|
||||
callback(arg, nbytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1052,6 +1052,7 @@ static int usbhost_mouse_poll(int argc, char *argv[])
|
||||
unsigned int npolls = 0;
|
||||
#endif
|
||||
unsigned int nerrors = 0;
|
||||
ssize_t nbytes;
|
||||
int ret;
|
||||
|
||||
uvdbg("Started\n");
|
||||
@@ -1084,14 +1085,14 @@ static int usbhost_mouse_poll(int argc, char *argv[])
|
||||
* sends data.
|
||||
*/
|
||||
|
||||
ret = DRVR_TRANSFER(hport->drvr, priv->epin,
|
||||
priv->tbuffer, priv->tbuflen);
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->epin,
|
||||
priv->tbuffer, priv->tbuflen);
|
||||
|
||||
/* Check for errors -- Bail if an excessive number of consecutive
|
||||
* errors are encountered.
|
||||
*/
|
||||
|
||||
if (ret < 0)
|
||||
if (nbytes < 0)
|
||||
{
|
||||
/* If DRVR_TRANSFER() returns EAGAIN, that simply means 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);
|
||||
if (ret != -EAGAIN)
|
||||
if (nbytes != -EAGAIN)
|
||||
{
|
||||
if (++nerrors > 200)
|
||||
{
|
||||
udbg("Too many errors... aborting: %d\n", nerrors);
|
||||
ret = (int)nbytes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
# error Asynchronous transfer support is required (CONFIG_USBHOST_ASYNCH)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBHOST_HUB_POLLMSEC
|
||||
#ifndef CONFIG_USBHOST_HUB_POLLMSEC
|
||||
# define CONFIG_USBHOST_HUB_POLLMSEC 400
|
||||
#endif
|
||||
|
||||
@@ -166,7 +166,7 @@ static void usbhost_disconnect_event(FAR void *arg);
|
||||
|
||||
static inline uint16_t usbhost_getle16(const uint8_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 */
|
||||
|
||||
@@ -1149,7 +1149,8 @@ static void usbhost_putle16(uint8_t *dest, uint16_t val)
|
||||
*
|
||||
* Input Parameters:
|
||||
* 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:
|
||||
* 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_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
|
||||
* end host controllers (like STM32 and EFM32), the transfer will fail
|
||||
* 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.
|
||||
*/
|
||||
|
||||
if (result != OK)
|
||||
if (nbytes < 0)
|
||||
{
|
||||
/* This debug output is good to know, but really a nuisance for
|
||||
* 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 (result != EAGAIN)
|
||||
if (nbytes != -EAGAIN)
|
||||
#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
|
||||
|
||||
@@ -711,7 +711,7 @@ static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv)
|
||||
{
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
FAR struct usbmsc_cbw_s *cbw;
|
||||
int result;
|
||||
ssize_t nbytes;
|
||||
|
||||
DEBUGASSERT(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 */
|
||||
|
||||
usbhost_testunitreadycbw(cbw);
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
(uint8_t*)cbw, USBMSC_CBW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Receive the CSW */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
priv->tbuffer, USBMSC_CSW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
FAR struct usbmsc_cbw_s *cbw;
|
||||
int result;
|
||||
ssize_t nbytes;
|
||||
|
||||
DEBUGASSERT(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 */
|
||||
|
||||
usbhost_requestsensecbw(cbw);
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
(uint8_t*)cbw, USBMSC_CBW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Receive the sense data response */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
priv->tbuffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Receive the CSW */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
priv->tbuffer, USBMSC_CSW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
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)
|
||||
@@ -795,7 +795,7 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
FAR struct usbmsc_cbw_s *cbw;
|
||||
FAR struct scsiresp_readcapacity10_s *resp;
|
||||
int result;
|
||||
ssize_t nbytes;
|
||||
|
||||
DEBUGASSERT(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 */
|
||||
|
||||
usbhost_readcapacitycbw(cbw);
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
(uint8_t*)cbw, USBMSC_CBW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* 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);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Save the capacity information */
|
||||
|
||||
@@ -830,23 +830,23 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
|
||||
|
||||
/* Receive the CSW */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
priv->tbuffer, USBMSC_CSW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
FAR struct usbhost_hubport_s *hport;
|
||||
FAR struct usbmsc_cbw_s *cbw;
|
||||
int result;
|
||||
ssize_t nbytes;
|
||||
|
||||
DEBUGASSERT(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 */
|
||||
|
||||
usbhost_inquirycbw(cbw);
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
(uint8_t*)cbw, USBMSC_CBW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Receive the CBW IN response */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
priv->tbuffer, SCSIRESP_INQUIRY_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
#if 0
|
||||
FAR struct scsiresp_inquiry_s *resp;
|
||||
|
||||
/* TODO: If USB debug is enabled, dump the response data here */
|
||||
|
||||
resp = (FAR struct scsiresp_inquiry_s *)priv->tbuffer;
|
||||
#endif
|
||||
|
||||
/* Receive the CSW */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
priv->tbuffer, USBMSC_CSW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
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_hubport_s *hport;
|
||||
ssize_t ret = 0;
|
||||
int result;
|
||||
ssize_t nbytes = 0;
|
||||
|
||||
DEBUGASSERT(inode && 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.
|
||||
*/
|
||||
|
||||
ret = -ENODEV;
|
||||
nbytes = -ENODEV;
|
||||
}
|
||||
else if (nsectors > 0)
|
||||
{
|
||||
@@ -2008,7 +2007,7 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
|
||||
|
||||
/* Assume allocation failure */
|
||||
|
||||
ret = -ENOMEM;
|
||||
nbytes = -ENOMEM;
|
||||
|
||||
/* 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 */
|
||||
|
||||
ret = -ENODEV;
|
||||
nbytes = -ENODEV;
|
||||
|
||||
/* Construct and send the 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);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Receive the user data */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
buffer, priv->blocksize * nsectors);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Receive the CSW */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
priv->tbuffer, USBMSC_CSW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
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;
|
||||
if (csw->status == 0)
|
||||
{
|
||||
ret = nsectors;
|
||||
nbytes = nsectors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (result == -EAGAIN);
|
||||
} while (nbytes == -EAGAIN);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
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_hubport_s *hport;
|
||||
ssize_t ret;
|
||||
int result;
|
||||
ssize_t nbytes;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
ret = -ENODEV;
|
||||
nbytes = -ENODEV;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2112,7 +2110,7 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
|
||||
|
||||
/* Assume allocation failure */
|
||||
|
||||
ret = -ENOMEM;
|
||||
nbytes = -ENOMEM;
|
||||
|
||||
/* 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 */
|
||||
|
||||
ret = -ENODEV;
|
||||
nbytes = -ENODEV;
|
||||
|
||||
/* Construct and send the 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);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Send the user data */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkout,
|
||||
(uint8_t*)buffer, priv->blocksize * nsectors);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
/* Receive the CSW */
|
||||
|
||||
result = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
nbytes = DRVR_TRANSFER(hport->drvr, priv->bulkin,
|
||||
priv->tbuffer, USBMSC_CSW_SIZEOF);
|
||||
if (result == OK)
|
||||
if (nbytes >= 0)
|
||||
{
|
||||
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;
|
||||
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 */
|
||||
|
||||
return ret;
|
||||
return nbytes < 0 ? (int)nbytes : OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -490,8 +490,9 @@
|
||||
* buflen - The length of the data to be sent or received.
|
||||
*
|
||||
* Returned Values:
|
||||
* On success, zero (OK) is returned. On a failure, a negated errno value is
|
||||
* returned indicating the nature of the failure:
|
||||
* On success, a non-negative value is returned that indicates the number
|
||||
* 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
|
||||
* it may be appropriate to restart the entire transaction).
|
||||
@@ -791,9 +792,13 @@ struct usbhost_connection_s
|
||||
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
|
||||
* USB host class implementation.
|
||||
@@ -869,8 +874,8 @@ struct usbhost_driver_s
|
||||
* transfer has completed.
|
||||
*/
|
||||
|
||||
int (*transfer)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
FAR uint8_t *buffer, size_t buflen);
|
||||
ssize_t (*transfer)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
||||
FAR uint8_t *buffer, size_t buflen);
|
||||
|
||||
/* Process a request to handle a transfer asynchronously. This method
|
||||
* will enqueue the transfer request and return immediately. Only one
|
||||
|
||||
Reference in New Issue
Block a user