From 08bd1c5ec26ce2fd1640d60dd2ca070b75de1f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Thu, 26 Oct 2023 09:17:46 +0200 Subject: [PATCH] usb: device: Fix ZLP write race condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ZLP packet has to be read and acknowledged by host just like any other DATA packet. Do not end transfer until the host actually acknowledged the trailing ZLP. This fixes the race condition between host and Zephyr application where the next transfer could be lost if host did not issue IN token (that would read read ZLP) before the application tried to start new transfer. Signed-off-by: Tomasz Moń --- subsys/usb/device/usb_transfer.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/subsys/usb/device/usb_transfer.c b/subsys/usb/device/usb_transfer.c index 7a75d87fd0c..95cf3198ab6 100644 --- a/subsys/usb/device/usb_transfer.c +++ b/subsys/usb/device/usb_transfer.c @@ -86,12 +86,17 @@ static void usb_transfer_work(struct k_work *item) if (trans->flags & USB_TRANS_WRITE) { if (!trans->bsize) { - if (!(trans->flags & USB_TRANS_NO_ZLP)) { - LOG_DBG("Transfer ZLP"); - usb_write(ep, NULL, 0, NULL); + if (trans->flags & USB_TRANS_NO_ZLP) { + trans->status = 0; + goto done; } - trans->status = 0; - goto done; + + /* Host have to read the ZLP just like any other DATA + * packet. Set USB_TRANS_NO_ZLP flag so the transfer + * will end next time we get ACK from host. + */ + LOG_DBG("Transfer ZLP"); + trans->flags |= USB_TRANS_NO_ZLP; } ret = usb_write(ep, trans->buffer, trans->bsize, &bytes);