Skip to content

Commit 3ae98de

Browse files
mathieuchopstmmarwaiehm-st
authored andcommitted
drivers: usb: udc: stm32: handle endpoint halt properly
Handle endpoints in halted state properly by marking endpoints as halted when appropriate, and inhibiting transfers involving halted endpoints. Co-authored-by: IBEN EL HADJ MESSAOUD Marwa <[email protected]> Signed-off-by: Mathieu CHOPLAIN <[email protected]>
1 parent ac79975 commit 3ae98de

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

drivers/usb/udc/udc_stm32.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,11 @@ static int udc_stm32_ep_set_halt(const struct device *dev,
844844
return -EIO;
845845
}
846846

847+
/* Mark endpoint as halted if not control EP */
848+
if (USB_EP_GET_IDX(cfg->addr) != 0U) {
849+
cfg->stat.halted = true;
850+
}
851+
847852
return 0;
848853
}
849854

@@ -852,6 +857,7 @@ static int udc_stm32_ep_clear_halt(const struct device *dev,
852857
{
853858
struct udc_stm32_data *priv = udc_get_private(dev);
854859
HAL_StatusTypeDef status;
860+
struct net_buf *buf;
855861

856862
LOG_DBG("Clear halt for ep 0x%02x", cfg->addr);
857863

@@ -862,6 +868,25 @@ static int udc_stm32_ep_clear_halt(const struct device *dev,
862868
return -EIO;
863869
}
864870

871+
/* Clear halt bit from endpoint status */
872+
cfg->stat.halted = false;
873+
874+
/* Check if there are transfers queued for EP */
875+
buf = udc_buf_peek(cfg);
876+
if (buf != NULL) {
877+
/*
878+
* There is at least one transfer pending.
879+
* IN EP transfer can be started only if not busy;
880+
* OUT EP transfer should be prepared only if busy.
881+
*/
882+
const bool busy = udc_ep_is_busy(cfg);
883+
884+
if (USB_EP_DIR_IS_IN(cfg->addr) && !busy) {
885+
udc_stm32_tx(dev, cfg, buf);
886+
} else if (USB_EP_DIR_IS_OUT(cfg->addr) && busy) {
887+
udc_stm32_rx(dev, cfg, buf);
888+
}
889+
}
865890
return 0;
866891
}
867892

@@ -888,14 +913,18 @@ static int udc_stm32_ep_enqueue(const struct device *dev,
888913
struct net_buf *buf)
889914
{
890915
unsigned int lock_key;
891-
int ret;
916+
int ret = 0;
892917

893918
udc_buf_put(epcfg, buf);
894919

895920
lock_key = irq_lock();
896921

897922
if (USB_EP_DIR_IS_IN(epcfg->addr)) {
898-
ret = udc_stm32_tx(dev, epcfg, buf);
923+
if (epcfg->stat.halted) {
924+
LOG_DBG("skip enqueue for halted ep 0x%02x", epcfg->addr);
925+
} else {
926+
ret = udc_stm32_tx(dev, epcfg, buf);
927+
}
899928
} else {
900929
ret = udc_stm32_rx(dev, epcfg, buf);
901930
}

0 commit comments

Comments
 (0)