If asynchronous tranfers are supported, then there must also be a mechanism to cancel the pending transfer

This commit is contained in:
Gregory Nutt 2015-04-24 11:23:52 -06:00
parent 2768f13153
commit 7d7ab442e1
4 changed files with 237 additions and 26 deletions

View File

@ -379,6 +379,7 @@ static void lpc17_asynch_completion(struct lpc17_usbhost_s *priv,
static int lpc17_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen,
usbhost_asynch_t callback, FAR void *arg);
static int lpc17_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
#endif
#ifdef CONFIG_USBHOST_HUB
static int lpc17_connect(FAR struct usbhost_driver_s *drvr,
@ -2943,7 +2944,74 @@ errout_with_sem:
lpc17_givesem(&priv->exclsem);
return ret;
}
#endif
#endif /* CONFIG_USBHOST_ASYNCH */
/************************************************************************************
* Name: DRVR_CANCEL
*
* Description:
* Cancel a pending asynchronous transfer on an endpoint.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* ep - The IN or OUT endpoint descriptor for the device endpoint on which an
* asynchronous transfer should be transferred.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure.
*
************************************************************************************/
#ifdef CONFIG_USBHOST_ASYNCH
static int lpc17_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
{
struct lpc17_ed_s *ed = (struct lpc17_ed_s *)ep;
struct lpc17_gtd_s *td;
struct lpc17_gtd_s *next;
struct lpc17_asynch_s *asynch;
irqstate_t flags;
int ret;
/* These first steps must be atomic as possible */
flags = irqsave();
/* It might be possible for no transfer to be in progress (asynch == NULL),
* but it would be an usage error to use the interface to try to cancel a
* synchronous transfer (wdhwait == true).
*/
DEBUGASSERT(ed != NULL && ed->wdhwait == false);
asynch = ed->asynch;
if (asynch)
{
/* We really need some kind of atomic test and set to do this right */
td = (struct lpc17_gtd_s *)ed->hw.headp;
ed->hw.headp = LPC17_TDTAIL_ADDR;
ed->asynch = NULL;
/* Free all transfer descriptors that were connected to the ED */
DEBUGASSERT(td != (struct lpc17_gtd_s *)LPC17_TDTAIL_ADDR);
while (td != (struct lpc17_gtd_s *)LPC17_TDTAIL_ADDR)
{
next = (struct lpc17_gtd_s *)td->hw.nexttd;
lpc17_tdfree(td);
td = next;
}
memset(asynch, 0, sizeof(struct lpc17_asynch_s));
lpc17_freeasynch(asynch);
}
ret = ed->wdhwait ? -EINVAL : OK;
irqrestore(flags);
return ret;
}
#endif /* CONFIG_USBHOST_ASYNCH */
/************************************************************************************
* Name: lpc17_connect
@ -3146,6 +3214,7 @@ struct usbhost_connection_s *lpc17_usbhost_initialize(int controller)
drvr->transfer = lpc17_transfer;
#ifdef CONFIG_USBHOST_ASYNCH
drvr->asynch = lpc17_asynch;
drvr->cancel = lpc17_cancel;
#endif
#ifdef CONFIG_USBHOST_HUB
drvr->connect = lpc17_connect;
@ -3269,7 +3338,7 @@ struct usbhost_connection_s *lpc17_usbhost_initialize(int controller)
buffer = (uint8_t *)LPC17_TDFREE_BASE;
for (i = 0; i < CONFIG_USBHOST_NTDS; i++)
{
/* Put the ED in a free list */
/* Put the TD in a free list */
lpc17_tdfree((struct lpc17_gtd_s *)buffer);
buffer += LPC17_TD_SIZE;

View File

@ -403,6 +403,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
static int sam_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen,
usbhost_asynch_t callback, FAR void *arg);
static int sam_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
#endif
#ifdef CONFIG_USBHOST_HUB
static int sam_connect(FAR struct usbhost_driver_s *drvr,
@ -3766,23 +3767,17 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
}
/*******************************************************************************
* Name: sam_transfer and sam_asynch
* Name: sam_transfer
*
* Description:
* Process a request to handle a transfer descriptor. This method will
* enqueue the transfer request and return immediately. Only one transfer may be
* queued;.
* enqueue the transfer request, blocking until the transfer completes. Only
* one transfer may be queued; Neither this method nor the ctrlin or
* ctrlout methods can be called again until this function returns.
*
* This is a blocking method; this functions will not return until the
* transfer has completed.
*
* - 'transfer' is a blocking method; this method will not return until the
* transfer has completed.
* - 'asynch' will return immediately. When the transfer completes, the
* the callback will be invoked with the provided transfer. This method
* is useful for receiving interrupt transfers which may come
* infrequently.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
@ -3791,10 +3786,6 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* buffer - A buffer containing the data to be sent (OUT endpoint) or received
* (IN endpoint). buffer must have been allocated using DRVR_ALLOC
* buflen - The length of the data to be sent or received.
* callback - This function will be called when the transfer completes ('asynch'
* only).
* arg - The arbitrary parameter that will be passed to the callback function
* when the transfer completes ('asynch' only).
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
@ -3807,7 +3798,6 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* EPIPE - Overrun errors
*
* Assumptions:
* - Only a single class bound to a single device is supported.
* - Called from a single thread so no mutual exclusion is required.
* - Never called from an interrupt handler.
*
@ -3855,6 +3845,41 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
return nbytes >=0 ? OK : (int)nbytes;
}
/*******************************************************************************
* Name: lcp17_asynch
*
* Description:
* Process a request to handle a transfer descriptor. This method will
* enqueue the transfer request and return immediately. When the transfer
* completes, the the callback will be invoked with the provided transfer.
* This method is useful for receiving interrupt transfers which may come
* infrequently.
*
* Only one transfer may be queued; Neither this method nor the ctrlin or
* ctrlout methods can be called again until the transfer completes.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* ep - The IN or OUT endpoint descriptor for the device endpoint on which to
* perform the transfer.
* buffer - A buffer containing the data to be sent (OUT endpoint) or received
* (IN endpoint). buffer must have been allocated using DRVR_ALLOC
* buflen - The length of the data to be sent or received.
* callback - This function will be called when the transfer completes.
* arg - The arbitrary parameter that will be passed to the callback function
* when the transfer completes.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
* Assumptions:
* - Called from a single thread so no mutual exclusion is required.
* - Never called from an interrupt handler.
*
*******************************************************************************/
#ifdef CONFIG_USBHOST_ASYNCH
static int sam_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen,
@ -3863,7 +3888,33 @@ static int sam_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
# error Not implemented
return -ENOSYS;
}
#endif
#endif /* CONFIG_USBHOST_ASYNCH */
/************************************************************************************
* Name: sam_cancel
*
* Description:
* Cancel a pending asynchronous transfer on an endpoint.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* ep - The IN or OUT endpoint descriptor for the device endpoint on which an
* asynchronous transfer should be transferred.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure.
*
************************************************************************************/
#ifdef CONFIG_USBHOST_ASYNCH
static int sam_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
{
# error Not implemented
return -ENOSYS;
}
#endif /* CONFIG_USBHOST_ASYNCH */
/************************************************************************************
* Name: sam_connect
@ -4216,6 +4267,7 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
rhport->drvr.transfer = sam_transfer;
#ifdef CONFIG_USBHOST_ASYNCH
rhport->drvr.asynch = sam_asynch;
rhport->drvr.cancel = sam_cancel;
#endif
#ifdef CONFIG_USBHOST_HUB
rhport->drvr.connect = sam_connect;

View File

@ -420,6 +420,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
static int sam_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen,
usbhost_asynch_t callback, FAR void *arg);
static int sam_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
#endif
#ifdef CONFIG_USBHOST_HUB
static int sam_connect(FAR struct usbhost_driver_s *drvr,
@ -2921,13 +2922,13 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
}
/*******************************************************************************
* Name: sam_transfer and sam_asynch
* Name: sam_transfer
*
* Description:
* Process a request to handle a transfer descriptor. This method will
* enqueue the transfer request and return immediately. Only one transfer may be
* queued; Neither this method nor the ctrlin or ctrlout methods can be called
* again until this function returns.
* enqueue the transfer request, blocking until the transfer completes. Only
* one transfer may be queued; Neither this method nor the ctrlin or
* ctrlout methods can be called again until this function returns.
*
* This is a blocking method; this functions will not return until the
* transfer has completed.
@ -2952,7 +2953,6 @@ static int sam_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
* EPIPE - Overrun errors
*
* Assumptions:
* - Only a single class bound to a single device is supported.
* - Called from a single thread so no mutual exclusion is required.
* - Never called from an interrupt handler.
*
@ -3098,6 +3098,41 @@ errout:
return ret;
}
/*******************************************************************************
* Name: lcp17_asynch
*
* Description:
* Process a request to handle a transfer descriptor. This method will
* enqueue the transfer request and return immediately. When the transfer
* completes, the the callback will be invoked with the provided transfer.
* This method is useful for receiving interrupt transfers which may come
* infrequently.
*
* Only one transfer may be queued; Neither this method nor the ctrlin or
* ctrlout methods can be called again until the transfer completes.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* ep - The IN or OUT endpoint descriptor for the device endpoint on which to
* perform the transfer.
* buffer - A buffer containing the data to be sent (OUT endpoint) or received
* (IN endpoint). buffer must have been allocated using DRVR_ALLOC
* buflen - The length of the data to be sent or received.
* callback - This function will be called when the transfer completes.
* arg - The arbitrary parameter that will be passed to the callback function
* when the transfer completes.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
* Assumptions:
* - Called from a single thread so no mutual exclusion is required.
* - Never called from an interrupt handler.
*
*******************************************************************************/
#ifdef CONFIG_USBHOST_ASYNCH
static int sam_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
FAR uint8_t *buffer, size_t buflen,
@ -3106,7 +3141,33 @@ static int sam_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
# error Not implemented
return -ENOSYS;
}
#endif
#endif /* CONFIG_USBHOST_ASYNCH */
/************************************************************************************
* Name: sam_cancel
*
* Description:
* Cancel a pending asynchronous transfer on an endpoint.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* ep - The IN or OUT endpoint descriptor for the device endpoint on which an
* asynchronous transfer should be transferred.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure.
*
************************************************************************************/
#ifdef CONFIG_USBHOST_ASYNCH
static int sam_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
{
# error Not implemented
return -ENOSYS;
}
#endif /* CONFIG_USBHOST_ASYNCH */
/************************************************************************************
* Name: sam_connect
@ -3365,6 +3426,7 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
rhport->drvr.transfer = sam_transfer;
#ifdef CONFIG_USBHOST_ASYNCH
rhport->drvr.asynch = sam_asynch;
rhport->drvr.cancel = sam_cancel;
#endif
#ifdef CONFIG_USBHOST_HUB
rhport->drvr.connect = sam_connect;

View File

@ -513,6 +513,28 @@
((drvr)->asynch(drvr,ep,buffer,buflen,callback,arg))
#endif
/************************************************************************************
* Name: DRVR_CANCEL
*
* Description:
* Cancel a pending asynchronous transfer on an endpoint.
*
* Input Parameters:
* drvr - The USB host driver instance obtained as a parameter from the call to
* the class create() method.
* ep - The IN or OUT endpoint descriptor for the device endpoint on which an
* asynchronous transfer should be transferred.
*
* Returned Values:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure.
*
************************************************************************************/
#ifdef CONFIG_USBHOST_ASYNCH
# define DRVR_CANCEL(drvr,ep) ((drvr)->cancel(drvr,ep))
#endif
/************************************************************************************
* Name: DRVR_CONNECT
*
@ -823,6 +845,12 @@ struct usbhost_driver_s
usbhost_asynch_t callback, FAR void *arg);
#endif
#ifdef CONFIG_USBHOST_ASYNCH
/* Cancel any pending asynchronous transfer on an endpoint */
int (*cancel)(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
#endif
#ifdef CONFIG_USBHOST_HUB
/* New connections may be detected by an attached hub. This method is the
* mechanism that is used by the hub class to introduce a new connection