git: fbedcad985b5 - stable/13 - Implement an API for sending a zero-length-packet. The purpose of such a USB packet is to toggle the binary packet counter for USB 1.0/2.0 protocols, without sending any data, so that the first packet sent after opening a USB BULK endpoint doesn't get lost. This is for devices not supporting the USB standard defined clear-stall handling.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 30 Apr 2023 06:58:09 UTC
The branch stable/13 has been updated by hselasky:
URL: https://cgit.FreeBSD.org/src/commit/?id=fbedcad985b52481991636a26409d6f55660a3f0
commit fbedcad985b52481991636a26409d6f55660a3f0
Author: Hans Petter Selasky <hselasky@FreeBSD.org>
AuthorDate: 2021-07-06 10:29:57 +0000
Commit: Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2023-04-30 06:56:18 +0000
Implement an API for sending a zero-length-packet. The purpose of such a
USB packet is to toggle the binary packet counter for USB 1.0/2.0 protocols,
without sending any data, so that the first packet sent after opening
a USB BULK endpoint doesn't get lost. This is for devices not supporting
the USB standard defined clear-stall handling.
Tested by: jmg
Sponsored by: NVIDIA Networking
(cherry picked from commit f83f5d58394db57576bbed6dc7531997cabeb102)
(cherry picked from commit ec97e9ca1fa543a4a803e84706564d41cd492065)
---
sys/dev/usb/usb_transfer.c | 59 +++++++++++++++++++++++++++++++++++++++++++---
sys/dev/usb/usbdi.h | 3 +++
2 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 455b23e2c306..20ed2c897aac 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008-2021 Hans Petter Selasky. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -2689,6 +2689,61 @@ usbd_transfer_start_cb(void *arg)
}
}
+/*------------------------------------------------------------------------*
+ * usbd_xfer_set_zlp
+ *
+ * This function sets the USB transfers ZLP flag.
+ *------------------------------------------------------------------------*/
+void
+usbd_xfer_set_zlp(struct usb_xfer *xfer)
+{
+ if (xfer == NULL) {
+ /* tearing down */
+ return;
+ }
+ USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
+
+ /* avoid any races by locking the USB mutex */
+ USB_BUS_LOCK(xfer->xroot->bus);
+ xfer->flags.send_zlp = 1;
+ USB_BUS_UNLOCK(xfer->xroot->bus);
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_xfer_get_and_clr_zlp
+ *
+ * This function gets and clears the USB transfers ZLP flag and
+ * queues a zero-length USB transfer if the flag was set.
+ *------------------------------------------------------------------------*/
+uint8_t
+usbd_xfer_get_and_clr_zlp(struct usb_xfer *xfer)
+{
+ uint8_t retval;
+
+ if (xfer == NULL) {
+ /* tearing down */
+ return (0);
+ }
+ USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
+
+ retval = xfer->flags.send_zlp;
+
+ if (retval != 0) {
+ DPRINTFN(1, "Sending zero-length packet.\n");
+
+ /* avoid any races by locking the USB mutex */
+ USB_BUS_LOCK(xfer->xroot->bus);
+ xfer->flags.send_zlp = 0;
+ USB_BUS_UNLOCK(xfer->xroot->bus);
+
+ /* queue up a zero-length packet */
+ usbd_xfer_set_frame_len(xfer, 0, 0);
+ usbd_xfer_set_frames(xfer, 1);
+ usbd_transfer_submit(xfer);
+ }
+ return (retval);
+}
+
/*------------------------------------------------------------------------*
* usbd_xfer_set_stall
*
@@ -2733,9 +2788,7 @@ usbd_transfer_clear_stall(struct usb_xfer *xfer)
/* avoid any races by locking the USB mutex */
USB_BUS_LOCK(xfer->xroot->bus);
-
xfer->flags.stall_pipe = 0;
-
USB_BUS_UNLOCK(xfer->xroot->bus);
}
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index 1b3b4af5f717..287e40d59364 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -218,6 +218,7 @@ struct usb_xfer_flags {
* option only has effect for
* ISOCHRONOUS transfers.
*/
+ uint8_t send_zlp:1; /* send a zero length packet first */
};
/*
@@ -655,6 +656,8 @@ void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex,
usb_frlength_t len);
void usbd_xfer_set_timeout(struct usb_xfer *xfer, int timeout);
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n);
+void usbd_xfer_set_zlp(struct usb_xfer *xfer);
+uint8_t usbd_xfer_get_and_clr_zlp(struct usb_xfer *xfer);
void usbd_xfer_set_stall(struct usb_xfer *xfer);
int usbd_xfer_is_stalled(struct usb_xfer *xfer);
void usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);