If asynchronous tranfers are supported, then there must also be a mechanism to cancel the pending transfer
This commit is contained in:
parent
2768f13153
commit
7d7ab442e1
@ -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,
|
||||
@ -682,8 +683,8 @@ static void lpc17_tdfree(struct lpc17_gtd_s *td)
|
||||
|
||||
if (tdfree != NULL && td != TDTAIL)
|
||||
{
|
||||
tdfree->flink = g_tdfree;
|
||||
g_tdfree = tdfree;
|
||||
tdfree->flink = g_tdfree;
|
||||
g_tdfree = tdfree;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user