Hi, (using private email as I'm having issue with company's VPN, will get that sorted out by tomorrow hopefully) > On Thu, 8 May 2014, Zhuang Jin Can wrote: > > > dwc3 _cannot_ return NYET to a SETUP packet. The USB protocol does > > > not > > > allow it. A device must always respond to SETUP with ACK. > > It true that device can not return NYET to a SETUP packet. > > A device must always respond to SETUP with ACK _if_ the SETUP packet > > is > > correctly received. Because there's no buffer prepared in ep0 for dwc3 > > to receive the SETUP packet, I guess there will be no handshake > > returned to host. I can confirm this by doing an experiment tomorrow:) > > The dwc3 driver should always prepare a buffer for the next ep0 SETUP > packet as soon as it retrieves the information for the current SETUP > packet from the buffer. > > Otherwise, as you described it, if the gadget driver never sends its > delayed status response then the UDC will never respond to any more > control transfers. we _do_ prepare transfers for setup packet everytime a Status phase is completed (we also restart ep0 in case of stalls): | static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) | { | struct dwc3_ep *dep; | | /* reinitialize physical ep1 */ | dep = dwc->eps[1]; | dep->flags = DWC3_EP_ENABLED; | | /* stall is always issued on EP0 */ | dep = dwc->eps[0]; | __dwc3_gadget_ep_set_halt(dep, 1); | dep->flags = DWC3_EP_ENABLED; | dwc->delayed_status = false; | | if (!list_empty(&dep->request_list)) { | struct dwc3_request *req; | | req = next_request(&dep->request_list); | dwc3_gadget_giveback(dep, req, -ECONNRESET); | } | | dwc->ep0state = EP0_SETUP_PHASE; | dwc3_ep0_out_start(dwc); | } [ ... ] | void dwc3_ep0_out_start(struct dwc3 *dwc) | { | int ret; | | ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8, | DWC3_TRBCTL_CONTROL_SETUP); | WARN_ON(ret < 0); | } [ ... ] | static void dwc3_ep0_complete_status(struct dwc3 *dwc, | const struct dwc3_event_depevt *event) | { | struct dwc3_request *r; | struct dwc3_ep *dep; | struct dwc3_trb *trb; | u32 status; | | dep = dwc->eps[0]; | trb = dwc->ep0_trb; | | if (!list_empty(&dep->request_list)) { | r = next_request(&dep->request_list); | | dwc3_gadget_giveback(dep, r, 0); | } | | if (dwc->test_mode) { | int ret; | | ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr); | if (ret < 0) { | dev_dbg(dwc->dev, "Invalid Test #%d\n", | dwc->test_mode_nr); | dwc3_ep0_stall_and_restart(dwc); | return; | } | } | | status = DWC3_TRB_SIZE_TRBSTS(trb->size); | if (status == DWC3_TRBSTS_SETUP_PENDING) | dev_dbg(dwc->dev, "Setup Pending received\n"); | | dwc->ep0state = EP0_SETUP_PHASE; | dwc3_ep0_out_start(dwc); | } -- balbi
Attachment:
signature.asc
Description: Digital signature