When changing the device address and max packet size in usbd_new_device(),
close and re-open the default pipe instead of relying on the host controller driver to notice the changes. Remove the unreliable code that attempted to update these fields while the pipe was active. This fixes a case where the hardware could cache and continue to use the old address, resulting in a "getting first desc failed" error. PR: usb/103167
This commit is contained in:
parent
2698dd58d9
commit
46a11df83f
@ -2903,17 +2903,6 @@ ehci_device_request(usbd_xfer_handle xfer)
|
||||
sqh->inactivesqtd = newinactive;
|
||||
epipe->u.ctl.length = len;
|
||||
|
||||
/* 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. */
|
||||
/* XXXX Should not touch ED here! */
|
||||
sqh->qh.qh_endp =
|
||||
(sqh->qh.qh_endp & htole32(~(EHCI_QH_ADDRMASK | EHCI_QH_MPLMASK))) |
|
||||
htole32(
|
||||
EHCI_QH_SET_ADDR(addr) |
|
||||
EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize))
|
||||
);
|
||||
|
||||
/* Set up data transaction */
|
||||
if (len != 0) {
|
||||
ehci_soft_qtd_t *end;
|
||||
|
@ -1765,16 +1765,6 @@ ohci_device_request(usbd_xfer_handle xfer)
|
||||
|
||||
sed = opipe->sed;
|
||||
opipe->u.ctl.length = len;
|
||||
|
||||
/* 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. */
|
||||
/* XXXX Should not touch ED here! */
|
||||
sed->ed.ed_flags = htole32(
|
||||
(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)));
|
||||
|
||||
next = stat;
|
||||
|
||||
/* Set up data transaction */
|
||||
|
@ -1110,6 +1110,15 @@ usbd_new_device(device_t parent, usbd_bus_handle bus, int depth,
|
||||
dev->address = addr; /* New device address now */
|
||||
bus->devices[addr] = dev;
|
||||
|
||||
/* Re-establish the default pipe with the new address. */
|
||||
usbd_kill_pipe(dev->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);
|
||||
}
|
||||
|
||||
dd = &dev->ddesc;
|
||||
/* Get the first 8 bytes of the device descriptor. */
|
||||
err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
|
||||
@ -1153,6 +1162,15 @@ usbd_new_device(device_t parent, usbd_bus_handle bus, int depth,
|
||||
|
||||
USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
|
||||
|
||||
/* Re-establish the default pipe with the new max packet size. */
|
||||
usbd_kill_pipe(dev->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);
|
||||
}
|
||||
|
||||
err = usbd_reload_device_desc(dev);
|
||||
if (err) {
|
||||
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
|
||||
|
Loading…
x
Reference in New Issue
Block a user