aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2021-07-06 10:29:57 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2021-07-15 10:11:53 +0000
commitf83f5d58394db57576bbed6dc7531997cabeb102 (patch)
tree36623792f9e3036c7c8d6002d12bd4f8405bbd9c /sys/dev/usb
parentb644d64e8a4641a6e4c53b3f4be51e08cb17f6cc (diff)
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/serial/u3g.c6
-rw-r--r--sys/dev/usb/serial/uark.c10
-rw-r--r--sys/dev/usb/serial/ubsa.c10
-rw-r--r--sys/dev/usb/serial/ubser.c10
-rw-r--r--sys/dev/usb/serial/uchcom.c6
-rw-r--r--sys/dev/usb/serial/ufoma.c10
-rw-r--r--sys/dev/usb/serial/uftdi.c6
-rw-r--r--sys/dev/usb/serial/ugensa.c11
-rw-r--r--sys/dev/usb/serial/uipaq.c10
-rw-r--r--sys/dev/usb/serial/ulpt.c9
-rw-r--r--sys/dev/usb/serial/umcs.c10
-rw-r--r--sys/dev/usb/serial/umodem.c18
-rw-r--r--sys/dev/usb/serial/umoscom.c10
-rw-r--r--sys/dev/usb/serial/uplcom.c21
-rw-r--r--sys/dev/usb/serial/uslcom.c10
-rw-r--r--sys/dev/usb/serial/uvscom.c10
-rw-r--r--sys/dev/usb/usb_transfer.c59
-rw-r--r--sys/dev/usb/usbdi.h3
18 files changed, 155 insertions, 74 deletions
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index 22e4e8f6b2bb..d7d8fd80b42a 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -978,8 +978,7 @@ u3g_attach(device_t dev)
/* set stall by default */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[nports][U3G_BULK_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[nports][U3G_BULK_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[nports][U3G_BULK_WR]);
mtx_unlock(&sc->sc_mtx);
nports++; /* found one port */
@@ -1100,6 +1099,9 @@ u3g_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_TRANSFERRED:
case USB_ST_SETUP:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
for (frame = 0; frame != U3G_TXFRAMES; frame++) {
usbd_xfer_set_frame_offset(xfer, frame * U3G_TXSIZE, frame);
diff --git a/sys/dev/usb/serial/uark.c b/sys/dev/usb/serial/uark.c
index 904977e1ec14..072edf6389cd 100644
--- a/sys/dev/usb/serial/uark.c
+++ b/sys/dev/usb/serial/uark.c
@@ -219,8 +219,7 @@ uark_attach(device_t dev)
}
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UARK_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UARK_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[UARK_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -281,13 +280,16 @@ uark_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
UARK_BUF_SIZE, &actlen)) {
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -295,7 +297,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/ubsa.c b/sys/dev/usb/serial/ubsa.c
index 10b37984db2f..3286df7331b4 100644
--- a/sys/dev/usb/serial/ubsa.c
+++ b/sys/dev/usb/serial/ubsa.c
@@ -320,8 +320,7 @@ ubsa_attach(device_t dev)
}
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UBSA_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UBSA_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[UBSA_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -583,13 +582,16 @@ ubsa_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
UBSA_BSIZE, &actlen)) {
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -597,7 +599,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/ubser.c b/sys/dev/usb/serial/ubser.c
index 2a35756b0a7e..61b9c6c433fb 100644
--- a/sys/dev/usb/serial/ubser.c
+++ b/sys/dev/usb/serial/ubser.c
@@ -293,8 +293,7 @@ ubser_attach(device_t dev)
ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UBSER_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UBSER_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[UBSER_BULK_DT_WR]);
usbd_transfer_start(sc->sc_xfer[UBSER_BULK_DT_RD]);
mtx_unlock(&sc->sc_mtx);
@@ -410,6 +409,9 @@ ubser_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
do {
if (ucom_get_data(sc->sc_ucom + sc->sc_curr_tx_unit,
@@ -430,7 +432,7 @@ tr_setup:
} while (sc->sc_curr_tx_unit != first_unit);
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -438,7 +440,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/uchcom.c b/sys/dev/usb/serial/uchcom.c
index 6b17141c6ece..aef1515d3586 100644
--- a/sys/dev/usb/serial/uchcom.c
+++ b/sys/dev/usb/serial/uchcom.c
@@ -350,8 +350,7 @@ uchcom_attach(device_t dev)
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UCHCOM_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UCHCOM_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[UCHCOM_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -828,6 +827,9 @@ uchcom_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
usbd_xfer_max_len(xfer), &actlen)) {
diff --git a/sys/dev/usb/serial/ufoma.c b/sys/dev/usb/serial/ufoma.c
index bc3f00a7b473..ca52752accad 100644
--- a/sys/dev/usb/serial/ufoma.c
+++ b/sys/dev/usb/serial/ufoma.c
@@ -438,8 +438,7 @@ ufoma_attach(device_t dev)
/* clear stall at first run, if any */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_bulk_xfer[UFOMA_BULK_ENDPT_WRITE]);
- usbd_xfer_set_stall(sc->sc_bulk_xfer[UFOMA_BULK_ENDPT_READ]);
+ usbd_xfer_set_zlp(sc->sc_bulk_xfer[UFOMA_BULK_ENDPT_WRITE]);
mtx_unlock(&sc->sc_mtx);
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -791,13 +790,16 @@ ufoma_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
UFOMA_BULK_BUF_SIZE, &actlen)) {
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -805,7 +807,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c
index 52977352fb94..9dc00e82253f 100644
--- a/sys/dev/usb/serial/uftdi.c
+++ b/sys/dev/usb/serial/uftdi.c
@@ -1117,8 +1117,7 @@ uftdi_attach(device_t dev)
}
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UFTDI_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UFTDI_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[UFTDI_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
/* set a valid "lcr" value */
@@ -1221,6 +1220,9 @@ uftdi_write_callback(struct usb_xfer *xfer, usb_error_t error)
/* FALLTHROUGH */
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
/*
* If output packets don't require headers (the common case) we
* can just load the buffer up with payload bytes all at once.
diff --git a/sys/dev/usb/serial/ugensa.c b/sys/dev/usb/serial/ugensa.c
index ba694e4805bd..1d2f1e57ef58 100644
--- a/sys/dev/usb/serial/ugensa.c
+++ b/sys/dev/usb/serial/ugensa.c
@@ -233,10 +233,8 @@ ugensa_attach(device_t dev)
break;
}
- /* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_WR]);
- usbd_xfer_set_stall(ssc->sc_xfer[UGENSA_BULK_DT_RD]);
+ usbd_xfer_set_zlp(ssc->sc_xfer[UGENSA_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
/* initialize port number */
@@ -313,13 +311,16 @@ ugensa_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(ssc->sc_ucom_ptr, pc, 0,
UGENSA_BUF_SIZE, &actlen)) {
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -327,7 +328,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/uipaq.c b/sys/dev/usb/serial/uipaq.c
index 33f2ae4c0845..0449a5663c71 100644
--- a/sys/dev/usb/serial/uipaq.c
+++ b/sys/dev/usb/serial/uipaq.c
@@ -1157,8 +1157,7 @@ uipaq_attach(device_t dev)
}
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UIPAQ_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UIPAQ_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[UIPAQ_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -1320,13 +1319,16 @@ uipaq_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
UIPAQ_BUF_SIZE, &actlen)) {
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -1334,7 +1336,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/ulpt.c b/sys/dev/usb/serial/ulpt.c
index c566da924374..56f99519d4cd 100644
--- a/sys/dev/usb/serial/ulpt.c
+++ b/sys/dev/usb/serial/ulpt.c
@@ -218,6 +218,9 @@ ulpt_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_TRANSFERRED:
case USB_ST_SETUP:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
max = usbd_xfer_max_len(xfer);
if (usb_fifo_get_data(f, pc, 0, max, &actlen, 0)) {
@@ -436,10 +439,6 @@ unlpt_open(struct usb_fifo *fifo, int fflags)
return (EBUSY);
}
if (fflags & FREAD) {
- /* clear stall first */
- mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[ULPT_BULK_DT_RD]);
- mtx_unlock(&sc->sc_mtx);
if (usb_fifo_alloc_buffer(fifo,
usbd_xfer_max_len(sc->sc_xfer[ULPT_BULK_DT_RD]),
ULPT_IFQ_MAXLEN)) {
@@ -451,7 +450,7 @@ unlpt_open(struct usb_fifo *fifo, int fflags)
if (fflags & FWRITE) {
/* clear stall first */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[ULPT_BULK_DT_WR]);
+ usbd_xfer_set_zlp(sc->sc_xfer[ULPT_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
if (usb_fifo_alloc_buffer(fifo,
usbd_xfer_max_len(sc->sc_xfer[ULPT_BULK_DT_WR]),
diff --git a/sys/dev/usb/serial/umcs.c b/sys/dev/usb/serial/umcs.c
index e3c8f1a764fb..76ecd1ffa452 100644
--- a/sys/dev/usb/serial/umcs.c
+++ b/sys/dev/usb/serial/umcs.c
@@ -382,8 +382,7 @@ umcs7840_attach(device_t dev)
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
for (subunit = 0; subunit < sc->sc_numports; ++subunit) {
- usbd_xfer_set_stall(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer[UMCS7840_BULK_RD_EP]);
- usbd_xfer_set_stall(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer[UMCS7840_BULK_WR_EP]);
+ usbd_xfer_set_zlp(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer[UMCS7840_BULK_WR_EP]);
}
mtx_unlock(&sc->sc_mtx);
@@ -916,13 +915,16 @@ umcs7840_write_callbackN(struct usb_xfer *xfer, usb_error_t error, uint8_t subun
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(ucom, pc, 0, usbd_xfer_max_len(xfer), &actlen)) {
DPRINTF("Port %d write, has %d bytes\n", ucom->sc_portno, actlen);
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -930,7 +932,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c
index 573d74cdb526..b8b7ae2f005c 100644
--- a/sys/dev/usb/serial/umodem.c
+++ b/sys/dev/usb/serial/umodem.c
@@ -447,13 +447,10 @@ umodem_attach(device_t dev)
goto detach;
}
- /* clear stall at first run, if USB host mode */
- if (uaa->usb_mode == USB_MODE_HOST) {
- mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_RD]);
- mtx_unlock(&sc->sc_mtx);
- }
+ /* send a ZLP at first run */
+ mtx_lock(&sc->sc_mtx);
+ usbd_xfer_set_zlp(sc->sc_xfer[UMODEM_BULK_WR]);
+ mtx_unlock(&sc->sc_mtx);
ucom_set_usb_mode(&sc->sc_super_ucom, uaa->usb_mode);
@@ -863,13 +860,16 @@ umodem_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
UMODEM_BUF_SIZE, &actlen)) {
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -877,7 +877,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/umoscom.c b/sys/dev/usb/serial/umoscom.c
index 724ab7f94092..536772a7f697 100644
--- a/sys/dev/usb/serial/umoscom.c
+++ b/sys/dev/usb/serial/umoscom.c
@@ -333,8 +333,7 @@ umoscom_attach(device_t dev)
}
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UMOSCOM_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UMOSCOM_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[UMOSCOM_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -639,13 +638,16 @@ umoscom_write_callback(struct usb_xfer *xfer, usb_error_t error)
tr_setup:
DPRINTF("\n");
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
UMOSCOM_BUFSIZE, &actlen)) {
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -654,7 +656,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/uplcom.c b/sys/dev/usb/serial/uplcom.c
index 9efac9ff6b7c..6808ddd64a4b 100644
--- a/sys/dev/usb/serial/uplcom.c
+++ b/sys/dev/usb/serial/uplcom.c
@@ -507,14 +507,12 @@ uplcom_attach(device_t dev)
goto detach;
}
- if (sc->sc_chiptype == TYPE_PL2303) {
- /* HX variants seem to lock up after a clear stall request. */
- mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]);
- mtx_unlock(&sc->sc_mtx);
- } else if (sc->sc_chiptype == TYPE_PL2303HX ||
- sc->sc_chiptype == TYPE_PL2303HXD) {
+ mtx_lock(&sc->sc_mtx);
+ usbd_xfer_set_zlp(sc->sc_xfer[UPLCOM_BULK_DT_WR]);
+ mtx_unlock(&sc->sc_mtx);
+
+ if (sc->sc_chiptype == TYPE_PL2303HX ||
+ sc->sc_chiptype == TYPE_PL2303HXD) {
/* reset upstream data pipes */
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE,
UPLCOM_SET_REQUEST, 8, 0, 0) ||
@@ -1094,6 +1092,9 @@ uplcom_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
UPLCOM_BULK_BUF_SIZE, &actlen)) {
@@ -1102,7 +1103,7 @@ tr_setup:
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -1110,7 +1111,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/uslcom.c b/sys/dev/usb/serial/uslcom.c
index fec18d2a5631..8c40a2c2fc3a 100644
--- a/sys/dev/usb/serial/uslcom.c
+++ b/sys/dev/usb/serial/uslcom.c
@@ -443,8 +443,7 @@ uslcom_attach(device_t dev)
}
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[USLCOM_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[USLCOM_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[USLCOM_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
sc->sc_partnum = uslcom_get_partnum(sc);
@@ -819,6 +818,9 @@ uslcom_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
USLCOM_BULK_BUF_SIZE, &actlen)) {
@@ -827,7 +829,7 @@ tr_setup:
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -835,7 +837,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/serial/uvscom.c b/sys/dev/usb/serial/uvscom.c
index 8bb69e4402cf..81fd5334a243 100644
--- a/sys/dev/usb/serial/uvscom.c
+++ b/sys/dev/usb/serial/uvscom.c
@@ -318,8 +318,7 @@ uvscom_attach(device_t dev)
/* clear stall at first run */
mtx_lock(&sc->sc_mtx);
- usbd_xfer_set_stall(sc->sc_xfer[UVSCOM_BULK_DT_WR]);
- usbd_xfer_set_stall(sc->sc_xfer[UVSCOM_BULK_DT_RD]);
+ usbd_xfer_set_zlp(sc->sc_xfer[UVSCOM_BULK_DT_WR]);
mtx_unlock(&sc->sc_mtx);
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -391,13 +390,16 @@ uvscom_write_callback(struct usb_xfer *xfer, usb_error_t error)
case USB_ST_SETUP:
case USB_ST_TRANSFERRED:
tr_setup:
+ if (usbd_xfer_get_and_clr_zlp(xfer))
+ break;
+
pc = usbd_xfer_get_frame(xfer, 0);
if (ucom_get_data(&sc->sc_ucom, pc, 0,
UVSCOM_BULK_BUF_SIZE, &actlen)) {
usbd_xfer_set_frame_len(xfer, 0, actlen);
usbd_transfer_submit(xfer);
}
- return;
+ break;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
@@ -405,7 +407,7 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
- return;
+ break;
}
}
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 436e08db14a1..e1582926b08d 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
@@ -2690,6 +2690,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
*
* This function is used to set the stall flag outside the
@@ -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);