diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index a66ac97992ab..3a39ba572e5a 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -1390,7 +1390,7 @@ ehci_open(usbd_pipe_handle pipe) if (sc->sc_dying) return (USBD_IOERROR); - epipe->nexttoggle = 0; + epipe->nexttoggle = pipe->endpoint->savedtoggle; if (addr == sc->sc_addr) { switch (ed->bEndpointAddress) { @@ -2479,6 +2479,8 @@ ehci_close_pipe(usbd_pipe_handle pipe, ehci_soft_qh_t *head) ehci_rem_qh(sc, sqh, head); splx(s); ehci_free_sqh(sc, epipe->sqh); + + pipe->endpoint->savedtoggle = epipe->nexttoggle; } /* diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 88ddfc7f3667..24e182e3114c 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -2161,7 +2161,9 @@ ohci_open(usbd_pipe_handle pipe) (dev->speed == USB_SPEED_LOW ? OHCI_ED_SPEED : 0) | fmt | OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize))); - sed->ed.ed_headp = sed->ed.ed_tailp = htole32(tdphys); + sed->ed.ed_headp = htole32(tdphys | + (pipe->endpoint->savedtoggle ? OHCI_TOGGLECARRY : 0)); + sed->ed.ed_tailp = htole32(tdphys); switch (xfertype) { case UE_CONTROL: @@ -2247,6 +2249,8 @@ ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) /* Make sure the host controller is not touching this ED */ usb_delay_ms(&sc->sc_bus, 1); splx(s); + pipe->endpoint->savedtoggle = + (le32toh(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; ohci_free_sed(sc, opipe->sed); } diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 05fdd1eddb18..b85a5b1048d1 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -2031,6 +2031,7 @@ uhci_device_bulk_close(usbd_pipe_handle pipe) uhci_softc_t *sc = (uhci_softc_t *)dev->bus; uhci_free_sqh(sc, upipe->u.bulk.sqh); + pipe->endpoint->savedtoggle = upipe->nexttoggle; } usbd_status @@ -2915,7 +2916,7 @@ uhci_open(usbd_pipe_handle pipe) ed->bEndpointAddress, sc->sc_addr)); upipe->aborting = 0; - upipe->nexttoggle = 0; + upipe->nexttoggle = pipe->endpoint->savedtoggle; if (pipe->device->address == sc->sc_addr) { switch (ed->bEndpointAddress) { diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index 655a4e3f124d..e1ceaf0ac04c 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -514,6 +514,7 @@ usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx) } } ifc->endpoints[endpt].refcnt = 0; + ifc->endpoints[endpt].savedtoggle = 0; p += ed->bLength; } #undef ed diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index 69f236638b1a..42537daa4785 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -51,6 +51,7 @@ struct usbd_pipe; struct usbd_endpoint { usb_endpoint_descriptor_t *edesc; int refcnt; + int savedtoggle; }; struct usbd_bus_methods {