mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 04:43:53 +00:00
Send a zero-length-packet first when opening a BULK endpoint for USB serial
port devices. If it gets eaten it is fine. Many USB device side implementations don't properly support the clear endpoint halt command and if they do, data is lost because the transmit FIFO is typically reset when this command is received. Tested by: jmg MFC after: 1 week Sponsored by: NVIDIA Networking
This commit is contained in:
parent
b644d64e8a
commit
f83f5d5839
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 @@ uark_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ ubsa_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ ubser_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
|
||||
} while (sc->sc_curr_tx_unit != first_unit);
|
||||
|
||||
return;
|
||||
break;
|
||||
|
||||
default: /* Error */
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
|
@ -438,7 +440,7 @@ ubser_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 @@ ufoma_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 @@ ugensa_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ uipaq_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]),
|
||||
|
|
|
@ -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 @@ umcs7840_write_callbackN(struct usb_xfer *xfer, usb_error_t error, uint8_t subun
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ umodem_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ umoscom_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ uplcom_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
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 @@ uplcom_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ uslcom_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
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 @@ uslcom_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ uvscom_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
|||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue