diff --git a/arch/arm/src/efm32/efm32_usbhost.c b/arch/arm/src/efm32/efm32_usbhost.c index c2743fd5f7..46158220f7 100644 --- a/arch/arm/src/efm32/efm32_usbhost.c +++ b/arch/arm/src/efm32/efm32_usbhost.c @@ -4696,11 +4696,14 @@ static int efm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static int efm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) { FAR struct efm32_usbhost_s *priv = (FAR struct efm32_usbhost_s *)drvr; + FAR struct efm32_chan_s *chan; unsigned int chidx = (unsigned int)ep; irqstate_t flags; uvdbg("chidx: %u: %d\n", chidx); + DEBUGASSERT(priv && chidx < EFM32_MAX_TX_FIFOS); + chan = &priv->chan[chidx]; /* We must have exclusive access to the USB host hardware and state structures. * And when we have that, we need to disable interrupts to avoid race conditions @@ -4713,6 +4716,44 @@ static int efm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) /* Halt the channel */ efm32_chan_halt(priv, chidx, CHREASON_CANCELLED); + chan->result = -ESHUTDOWN; + + /* Is there a thread waiting for this transfer to complete? */ + + if (chan->waiter) + { + /* Yes.. there should not also be a callback scheduled */ + + DEBUGASSERT(chan->callback == NULL); + + /* Wake'em up! */ + + efm32_givesem(&chan->waitsem); + chan->waiter = false; + } + + /* No.. is an asynchronous callback expected when the transfer + * completes? + */ + + else if (chan->callback) + { + usbhost_asynch_t callback; + FAR void *arg; + + /* Extract the callback information */ + + callback = chan->callback; + arg = chan->arg; + + chan->callback = NULL; + chan->arg = NULL; + chan->xfrd = 0; + + /* Then perform the callback */ + + callback(arg, -ESHUTDOWN); + } irqrestore(flags); efm32_givesem(&priv->exclsem); diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c index bcc4eebe2a..51d43e3278 100644 --- a/arch/arm/src/lpc17xx/lpc17_usbhost.c +++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c @@ -3289,6 +3289,10 @@ static int lpc17_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) if (xfrinfo->wdhwait) { + /* Yes.. there should not also be a callback scheduled */ + + DEBUGASSERT(xfrinfo->callback == NULL); + /* Wake up the waiting thread */ lpc17_givesem(&ed->wdhsem); diff --git a/arch/arm/src/sama5/sam_ohci.c b/arch/arm/src/sama5/sam_ohci.c index d163ba0b20..a13551b065 100644 --- a/arch/arm/src/sama5/sam_ohci.c +++ b/arch/arm/src/sama5/sam_ohci.c @@ -3669,6 +3669,12 @@ static int sam_cancel(struct usbhost_driver_s *drvr, usbhost_ep_t ep) if (eplist->wdhwait) { + /* Yes.. there should not also be a callback scheduled */ + + DEBUGASSERT(eplist->callback == NULL); + + /* Wake up the waiting thread */ + sam_givesem(&eplist->wdhsem); eplist->wdhwait = false; } diff --git a/arch/arm/src/stm32/stm32_otgfshost.c b/arch/arm/src/stm32/stm32_otgfshost.c index 4791cdfae5..2774568202 100644 --- a/arch/arm/src/stm32/stm32_otgfshost.c +++ b/arch/arm/src/stm32/stm32_otgfshost.c @@ -4628,11 +4628,14 @@ static int stm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static int stm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) { FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; + FAR struct stm32_chan_s *chan; unsigned int chidx = (unsigned int)ep; irqstate_t flags; uvdbg("chidx: %u: %d\n", chidx); + DEBUGASSERT(priv && chidx < STM32_MAX_TX_FIFOS); + chan = &priv->chan[chidx]; /* We must have exclusive access to the USB host hardware and state structures. * And when we have that, we need to disable interrupts to avoid race conditions @@ -4645,6 +4648,44 @@ static int stm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) /* Halt the channel */ stm32_chan_halt(priv, chidx, CHREASON_CANCELLED); + chan->result = -ESHUTDOWN; + + /* Is there a thread waiting for this transfer to complete? */ + + if (chan->waiter) + { + /* Yes.. there should not also be a callback scheduled */ + + DEBUGASSERT(chan->callback == NULL); + + /* Wake'em up! */ + + stm32_givesem(&chan->waitsem); + chan->waiter = false; + } + + /* No.. is an asynchronous callback expected when the transfer + * completes? + */ + + else if (chan->callback) + { + usbhost_asynch_t callback; + FAR void *arg; + + /* Extract the callback information */ + + callback = chan->callback; + arg = chan->arg; + + chan->callback = NULL; + chan->arg = NULL; + chan->xfrd = 0; + + /* Then perform the callback */ + + callback(arg, -ESHUTDOWN); + } irqrestore(flags); stm32_givesem(&priv->exclsem); diff --git a/arch/arm/src/stm32/stm32_otghshost.c b/arch/arm/src/stm32/stm32_otghshost.c index 4856040a64..28bece03d5 100644 --- a/arch/arm/src/stm32/stm32_otghshost.c +++ b/arch/arm/src/stm32/stm32_otghshost.c @@ -4628,11 +4628,14 @@ static int stm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, static int stm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) { FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; + FAR struct stm32_chan_s *chan; unsigned int chidx = (unsigned int)ep; irqstate_t flags; uvdbg("chidx: %u: %d\n", chidx); + DEBUGASSERT(priv && chidx < STM32_MAX_TX_FIFOS); + chan = &priv->chan[chidx]; /* We must have exclusive access to the USB host hardware and state structures. * And when we have that, we need to disable interrupts to avoid race conditions @@ -4645,6 +4648,44 @@ static int stm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) /* Halt the channel */ stm32_chan_halt(priv, chidx, CHREASON_CANCELLED); + chan->result = -ESHUTDOWN; + + /* Is there a thread waiting for this transfer to complete? */ + + if (chan->waiter) + { + /* Yes.. there should not also be a callback scheduled */ + + DEBUGASSERT(chan->callback == NULL); + + /* Wake'em up! */ + + stm32_givesem(&chan->waitsem); + chan->waiter = false; + } + + /* No.. is an asynchronous callback expected when the transfer + * completes? + */ + + else if (chan->callback) + { + usbhost_asynch_t callback; + FAR void *arg; + + /* Extract the callback information */ + + callback = chan->callback; + arg = chan->arg; + + chan->callback = NULL; + chan->arg = NULL; + chan->xfrd = 0; + + /* Then perform the callback */ + + callback(arg, -ESHUTDOWN); + } irqrestore(flags); stm32_givesem(&priv->exclsem);