On Tue, Aug 21, 2012 at 1:34 PM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote: >> It is a silicon feature: the core will intercept SET_CONFIGURATION / >> SET_INTERFACE requests, store wValue/wIndex in the appropriate >> USBD_STATUS_REG field (cfg/intf/altintf), send an acknowledgement to >> the host, and raise a control interrupt. > > Your explanation is not clear. The operations you listed are exactly > what any UDC should do when it receives any control request: It should > store the bRequestType, bRequest, wValue, wIndex, and wLength values in > appropriate registers, send an ACK back to the host, and generate an > IRQ. What's special about Set-Config and Set-Interface? For "most" control requests (such as GET_DESCRIPTOR), this core writes the raw packet data out to a buffer in DRAM and raises an IUDMA IRQ. The UDC driver passes this data on to the gadget driver and allows it to decide what to send back in subsequent phases. But some requests are handled entirely in hardware, including the status phase: SET_ADDRESS SET_CONFIGURATION SET_INTERFACE SET_FEATURE CLEAR_FEATURE GET_FEATURE Where appropriate, the hardware block will update its registers to indicate the new settings and raise a control IRQ. >> I haven't found it to be terribly helpful, but I don't know of a way >> to turn it off. > > Why would you want to turn this off? Isn't is exactly what you want to > have happen? And why do you need a workqueue to handle the request? SET_CONFIGURATION and SET_INTERFACE need to generate setup callbacks for the gadget driver, and the proper ordering of events needs to be enforced. It is possible to receive IRQs for "SET_CONFIGURATION has happened," "SET_INTERFACE has happened," and "there is another control request pending," all at nearly the same time, before the gadget driver has had an opportunity to respond to the first setup request. But if that happened, we would not want to generate three setup callbacks in a row. Example: 1) SET_CONFIGURATION transfer completes (including status phase), all handled by hardware. Control interrupt is raised. 2) Setup packet is sent to USB gadget driver (say, gadgetfs) 3) SET_INTERFACE transfer completes, and another control interrupt is raised 4) Gadget driver eventually gets around to queuing the SET_CONFIGURATION reply. 5) Now we are in the UDC queue function and the gadget driver is probably holding a spinlock. We want to invoke the setup callback with the spoofed SET_INTERFACE packet, but it's not safe to do it from here. To complicate the situation, another setup packet can arrive between steps 3 and 4. But the worker function makes sure everything plays out in the right order.