mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +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).
|
(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
@@ -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
@@ -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,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,
|
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;
|
||||||
struct lpc31_epinfo_s *epinfo = (struct lpc31_epinfo_s *)ep;
|
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);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,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,
|
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;
|
||||||
struct sam_epinfo_s *epinfo = (struct sam_epinfo_s *)ep;
|
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);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|||||||
@@ -219,14 +219,15 @@
|
|||||||
|
|
||||||
struct sam_eplist_s
|
struct sam_eplist_s
|
||||||
{
|
{
|
||||||
volatile bool wdhwait; /* TRUE: Thread is waiting for WDH interrupt */
|
volatile bool wdhwait; /* TRUE: Thread is waiting for WDH interrupt */
|
||||||
sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */
|
sem_t wdhsem; /* Semaphore used to wait for Writeback Done Head event */
|
||||||
#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,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,
|
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);
|
||||||
static int sam_asynch(struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
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 *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);
|
||||||
else
|
|
||||||
{
|
sam_givesem(&g_ohci.exclsem);
|
||||||
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, RHPORT(rhport),
|
return nbytes;
|
||||||
ed->tdstatus);
|
|
||||||
ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A transfer error occurred */
|
||||||
|
|
||||||
|
usbhost_trace2(OHCI_TRACE2_BADTDSTATUS, RHPORT(rhport), ed->tdstatus);
|
||||||
|
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
|
||||||
|
|
||||||
|
|||||||
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;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,8 +874,8 @@ 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
|
||||||
* will enqueue the transfer request and return immediately. Only one
|
* will enqueue the transfer request and return immediately. Only one
|
||||||
|
|||||||
Reference in New Issue
Block a user