From 973f914b90a2e204165e9e32cdf4a653acc00cd9 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 23 Oct 2024 11:23:23 +0200 Subject: [PATCH] drivers: udc_nrf: fix enqueue of control IN transfer with length 0 If the direction of the last setup packet is not to the device but to the host, then the transfer is not a status stage and should be queued. This is not checked and prevents a zero length control IN transfer to the host, e.g. used by the DFU class to indicate the end of the upload process. Signed-off-by: Johann Fischer --- drivers/usb/udc/udc_nrf.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/udc/udc_nrf.c b/drivers/usb/udc/udc_nrf.c index c024d2a6a18..2d1eb17d472 100644 --- a/drivers/usb/udc/udc_nrf.c +++ b/drivers/usb/udc/udc_nrf.c @@ -487,7 +487,7 @@ static void udc_nrf_power_handler(nrfx_power_usb_evt_t pwr_evt) } } -static void udc_nrf_fake_status_in(const struct device *dev) +static bool udc_nrf_fake_status_in(const struct device *dev) { struct udc_nrf_evt evt = { .type = UDC_NRF_EVT_STATUS_IN, @@ -497,7 +497,10 @@ static void udc_nrf_fake_status_in(const struct device *dev) if (nrf_usbd_common_last_setup_dir_get() == USB_CONTROL_EP_OUT) { /* Let controller perform status IN stage */ k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + return true; } + + return false; } static int udc_nrf_ep_enqueue(const struct device *dev, @@ -512,8 +515,9 @@ static int udc_nrf_ep_enqueue(const struct device *dev, udc_buf_put(cfg, buf); if (cfg->addr == USB_CONTROL_EP_IN && buf->len == 0) { - udc_nrf_fake_status_in(dev); - return 0; + if (udc_nrf_fake_status_in(dev)) { + return 0; + } } k_msgq_put(&drv_msgq, &evt, K_NO_WAIT);