ChangeSet 1.1188, 2003/05/20 12:10:28-07:00, david-b@pacbell.net [PATCH] USB: disable usb device endpoints in more places This patch touches the most significant places in usbcore that need to respond to configuration change events: - set_interface changes altsettings; affects endpoints in both new and old settings (but not other endpoints). - set_configuration; affects every endpoint The endpoints get disabled, flushing hardware state reliably. This resolves two FIXMEs here, part of one in OHCI (ed_get) and all of one in EHCI (qh_append_tds). Not many drivers currently use these code paths, but now they should start to work properly. diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c Tue May 20 17:24:49 2003 +++ b/drivers/usb/core/message.c Tue May 20 17:24:49 2003 @@ -795,6 +795,7 @@ struct usb_interface *iface; struct usb_host_interface *iface_as; int i, ret; + void (*disable)(struct usb_device *, int) = dev->bus->op->disable; iface = usb_ifnum_to_if(dev, interface); if (!iface) { @@ -832,9 +833,11 @@ u8 ep = iface_as->endpoint [i].desc.bEndpointAddress; int out = !(ep & USB_DIR_IN); + /* clear out hcd state, then usbcore state */ + if (disable) + disable (dev, ep); ep &= USB_ENDPOINT_NUMBER_MASK; (out ? dev->epmaxpacketout : dev->epmaxpacketin ) [ep] = 0; - // FIXME want hcd hook here, "no such endpoint" } iface->act_altsetting = alternate; @@ -898,6 +901,7 @@ { int i, ret; struct usb_host_config *cp = NULL; + void (*disable)(struct usb_device *, int) = dev->bus->op->disable; for (i=0; idescriptor.bNumConfigurations; i++) { if (dev->config[i].desc.bConfigurationValue == configuration) { @@ -911,11 +915,15 @@ } /* if it's already configured, clear out old state first. */ - if (dev->state != USB_STATE_ADDRESS) { - /* FIXME unbind drivers from all "old" interfaces. - * handshake with hcd to reset cached hc endpoint state. - */ + if (dev->state != USB_STATE_ADDRESS && disable) { + for (i = 0; i < 15; i++) { + disable (dev, i); + disable (dev, USB_DIR_IN | i); + } } + dev->toggle[0] = dev->toggle[1] = 0; + dev->halted[0] = dev->halted[1] = 0; + dev->state = USB_STATE_ADDRESS; if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, @@ -923,15 +931,9 @@ return ret; if (configuration) dev->state = USB_STATE_CONFIGURED; - else - dev->state = USB_STATE_ADDRESS; dev->actconfig = cp; /* reset more hc/hcd endpoint state */ - dev->toggle[0] = 0; - dev->toggle[1] = 0; - dev->halted[0] = 0; - dev->halted[1] = 0; usb_set_maxpacket(dev); return 0;