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).
* 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
+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
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
+20 -15
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);
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;
}
+21 -16
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);
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;
}
/*******************************************************************************
+40 -22
View File
@@ -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
+6 -4
View File
@@ -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;
}
}
+10 -9
View File
@@ -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
+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 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
+11 -6
View File
@@ -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