diff --git a/sys/bus/usb/ehci.c b/sys/bus/usb/ehci.c index 076bad7..66881fc 100644 --- a/sys/bus/usb/ehci.c +++ b/sys/bus/usb/ehci.c @@ -1370,6 +1370,7 @@ ehci_open(usbd_pipe_handle pipe) bad1: ehci_free_sqh(sc, sqh); + epipe->sqh = NULL; bad0: return (USBD_NOMEM); } @@ -2648,11 +2649,11 @@ ehci_device_request(usbd_xfer_handle xfer) usb_device_request_t *req = &xfer->request; usbd_device_handle dev = epipe->pipe.device; ehci_softc_t *sc = (ehci_softc_t *)dev->bus; - int addr = dev->address; ehci_soft_qtd_t *setup, *stat, *next; ehci_soft_qh_t *sqh; int isread; int len; + int addr = dev->address; usbd_status err; isread = req->bmRequestType & UT_READ; @@ -2661,7 +2662,7 @@ ehci_device_request(usbd_xfer_handle xfer) DPRINTFN(3,("ehci_device_request: type=0x%02x, request=0x%02x, " "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n", req->bmRequestType, req->bRequest, UGETW(req->wValue), - UGETW(req->wIndex), len, addr, + UGETW(req->wIndex), len, dev->address, epipe->pipe.endpoint->edesc->bEndpointAddress)); setup = ehci_alloc_sqtd(sc); @@ -2678,6 +2679,7 @@ ehci_device_request(usbd_xfer_handle xfer) sqh = epipe->sqh; epipe->u.ctl.length = len; +#if 1 /* Update device address and length since they may have changed during the setup of the control pipe in usbd_new_device(). */ /* XXX This only needs to be done once, but it's too early in open. */ @@ -2688,6 +2690,7 @@ ehci_device_request(usbd_xfer_handle xfer) EHCI_QH_SET_ADDR(addr) | EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize)) ); +#endif /* Set up data transaction */ if (len != 0) { diff --git a/sys/bus/usb/ohci.c b/sys/bus/usb/ohci.c index 1c07031..0f3548a 100644 --- a/sys/bus/usb/ohci.c +++ b/sys/bus/usb/ohci.c @@ -341,11 +341,16 @@ ohci_detach(struct ohci_softc *sc, int flags) usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ - for (i = 0; i < OHCI_NO_EDS; i++) + for (i = 0; i < OHCI_NO_EDS; i++) { ohci_free_sed(sc, sc->sc_eds[i]); + sc->sc_eds[i] = NULL; + } ohci_free_sed(sc, sc->sc_isoc_head); + sc->sc_isoc_head = NULL; ohci_free_sed(sc, sc->sc_bulk_head); + sc->sc_bulk_head = NULL; ohci_free_sed(sc, sc->sc_ctrl_head); + sc->sc_ctrl_head = NULL; usb_freemem(&sc->sc_bus, &sc->sc_hccadma); return (rv); @@ -706,8 +711,10 @@ ohci_init(ohci_softc_t *sc) for (i = 0; i < OHCI_NO_EDS; i++) { sed = ohci_alloc_sed(sc); if (sed == NULL) { - while (--i >= 0) + while (--i >= 0) { ohci_free_sed(sc, sc->sc_eds[i]); + sc->sc_eds[i] = NULL; + } err = USBD_NOMEM; goto bad4; } @@ -765,14 +772,19 @@ ohci_init(ohci_softc_t *sc) return (USBD_NORMAL_COMPLETION); bad5: - for (i = 0; i < OHCI_NO_EDS; i++) + for (i = 0; i < OHCI_NO_EDS; i++) { ohci_free_sed(sc, sc->sc_eds[i]); + sc->sc_eds[i] = NULL; + } bad4: ohci_free_sed(sc, sc->sc_isoc_head); + sc->sc_isoc_head = NULL; bad3: ohci_free_sed(sc, sc->sc_bulk_head); + sc->sc_bulk_head = NULL; bad2: ohci_free_sed(sc, sc->sc_ctrl_head); + sc->sc_ctrl_head = NULL; bad1: usb_freemem(&sc->sc_bus, &sc->sc_hccadma); return (err); @@ -1701,6 +1713,7 @@ ohci_device_request(usbd_xfer_handle xfer) sed = opipe->sed; opipe->u.ctl.length = len; +#if 1 /* Update device address and length since they may have changed during the setup of the control pipe in usbd_new_device(). */ /* XXX This only needs to be done once, but it's too early in open. */ @@ -1709,6 +1722,7 @@ ohci_device_request(usbd_xfer_handle xfer) (le32toh(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) | OHCI_ED_SET_FA(addr) | OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize))); +#endif next = stat; @@ -2149,8 +2163,10 @@ ohci_open(usbd_pipe_handle pipe) if (std != NULL) ohci_free_std(sc, std); bad1: - if (sed != NULL) + if (sed != NULL) { ohci_free_sed(sc, sed); + opipe->sed = NULL; + } bad0: return (USBD_NOMEM); @@ -2200,6 +2216,7 @@ ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) pipe->endpoint->savedtoggle = (le32toh(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; ohci_free_sed(sc, opipe->sed); + opipe->sed = NULL; } /* @@ -3168,7 +3185,9 @@ ohci_device_intr_close(usbd_pipe_handle pipe) --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS]; ohci_free_std(sc, opipe->tail.td); + opipe->tail.td = NULL; ohci_free_sed(sc, opipe->sed); + opipe->sed = NULL; } static usbd_status diff --git a/sys/bus/usb/usb_subr.c b/sys/bus/usb/usb_subr.c index d910b4b..b810af0 100644 --- a/sys/bus/usb/usb_subr.c +++ b/sys/bus/usb/usb_subr.c @@ -691,7 +691,7 @@ usbd_setup_pipe(usbd_device_handle dev, usbd_interface_handle iface, DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n", dev, iface, ep, pipe)); - p = kmalloc(dev->bus->pipe_size, M_USB, M_INTWAIT); + p = kmalloc(dev->bus->pipe_size, M_USB, M_INTWAIT | M_ZERO); p->device = dev; p->iface = iface; p->endpoint = ep; @@ -1012,11 +1012,26 @@ usbd_new_device(device_t parent, usbd_bus_handle bus, int depth, usbd_remove_device(dev, up); return (err); } + /* Allow device time to set new address */ usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE); + + /* Kill the pipe */ + usbd_kill_pipe(dev->default_pipe); + dev->default_pipe = NULL; + dev->address = addr; /* New device address now */ bus->devices[addr] = dev; + /* Re-establish the default pipe. */ + err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL, + &dev->default_pipe); + if (err) { + usbd_remove_device(dev, up); + return (err); + } + usbd_delay_ms(dev, 200); + dd = &dev->ddesc; /* Get the first 8 bytes of the device descriptor. */ err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);