diff --git a/arch/arm/src/efm32/efm32_usbhost.c b/arch/arm/src/efm32/efm32_usbhost.c index 8da27b98b8..9f4e5aa8cf 100644 --- a/arch/arm/src/efm32/efm32_usbhost.c +++ b/arch/arm/src/efm32/efm32_usbhost.c @@ -185,7 +185,8 @@ enum efm32_chreason_e CHREASON_STALL, /* Endpoint stalled */ CHREASON_TXERR, /* Transfer error received */ CHREASON_DTERR, /* Data toggle error received */ - CHREASON_FRMOR /* Frame overrun */ + CHREASON_FRMOR, /* Frame overrun */ + CHREASON_CANCELLED /* Transfer cancelled */ }; /* This structure retains the state of one host channel. NOTE: Since there @@ -4546,9 +4547,29 @@ static int efm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, #ifdef CONFIG_USBHOST_ASYNCH static int efm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) { -# error Missing logic - return -ENOSYS; - } + FAR struct efm32_usbhost_s *priv = (FAR struct efm32_usbhost_s *)drvr; + unsigned int chidx = (unsigned int)ep; + irqstate_t flags; + + uvdbg("chidx: %u: %d\n", chidx); + DEBUGASSERT(priv && chidx < EFM32_MAX_TX_FIFOS); + + /* 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 + * with the asynchronous completion of the transfer being cancelled. + */ + + efm32_takesem(&priv->exclsem); + flags = irqsave(); + + /* Halt the channel */ + + efm32_chan_halt(priv, chidx, CHREASON_CANCELLED); + + irqrestore(flags); + efm32_givesem(&priv->exclsem); + return OK; +} #endif /* CONFIG_USBHOST_ASYNCH */ /************************************************************************************ diff --git a/arch/arm/src/stm32/stm32_otgfshost.c b/arch/arm/src/stm32/stm32_otgfshost.c index 8387acef1b..c030241169 100644 --- a/arch/arm/src/stm32/stm32_otgfshost.c +++ b/arch/arm/src/stm32/stm32_otgfshost.c @@ -192,7 +192,8 @@ enum stm32_chreason_e CHREASON_STALL, /* Endpoint stalled */ CHREASON_TXERR, /* Transfer error received */ CHREASON_DTERR, /* Data toggle error received */ - CHREASON_FRMOR /* Frame overrun */ + CHREASON_FRMOR, /* Frame overrun */ + CHREASON_CANCELLED /* Transfer cancelled */ }; /* This structure retains the state of one host channel. NOTE: Since there @@ -4594,9 +4595,29 @@ static int stm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, #ifdef CONFIG_USBHOST_ASYNCH static int stm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) { -# error Missing logic - return -ENOSYS; - } + FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; + unsigned int chidx = (unsigned int)ep; + irqstate_t flags; + + uvdbg("chidx: %u: %d\n", chidx); + DEBUGASSERT(priv && chidx < STM32_MAX_TX_FIFOS); + + /* 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 + * with the asynchronous completion of the transfer being cancelled. + */ + + stm32_takesem(&priv->exclsem); + flags = irqsave(); + + /* Halt the channel */ + + stm32_chan_halt(priv, chidx, CHREASON_CANCELLED); + + irqrestore(flags); + stm32_givesem(&priv->exclsem); + return OK; +} #endif /* CONFIG_USBHOST_ASYNCH */ /************************************************************************************ diff --git a/arch/arm/src/stm32/stm32_otghshost.c b/arch/arm/src/stm32/stm32_otghshost.c index c4d52ceac6..e85105dc23 100644 --- a/arch/arm/src/stm32/stm32_otghshost.c +++ b/arch/arm/src/stm32/stm32_otghshost.c @@ -192,7 +192,8 @@ enum stm32_chreason_e CHREASON_STALL, /* Endpoint stalled */ CHREASON_TXERR, /* Transfer error received */ CHREASON_DTERR, /* Data toggle error received */ - CHREASON_FRMOR /* Frame overrun */ + CHREASON_FRMOR, /* Frame overrun */ + CHREASON_CANCELLED /* Transfer cancelled */ }; /* This structure retains the state of one host channel. NOTE: Since there @@ -4594,9 +4595,29 @@ static int stm32_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, #ifdef CONFIG_USBHOST_ASYNCH static int stm32_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep) { -# error Missing logic - return -ENOSYS; - } + FAR struct stm32_usbhost_s *priv = (FAR struct stm32_usbhost_s *)drvr; + unsigned int chidx = (unsigned int)ep; + irqstate_t flags; + + uvdbg("chidx: %u: %d\n", chidx); + DEBUGASSERT(priv && chidx < STM32_MAX_TX_FIFOS); + + /* 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 + * with the asynchronous completion of the transfer being cancelled. + */ + + stm32_takesem(&priv->exclsem); + flags = irqsave(); + + /* Halt the channel */ + + stm32_chan_halt(priv, chidx, CHREASON_CANCELLED); + + irqrestore(flags); + stm32_givesem(&priv->exclsem); + return OK; +} #endif /* CONFIG_USBHOST_ASYNCH */ /************************************************************************************