int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags) { struct dwc3_request *req = to_dwc3_request(request); struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3 *dwc = dep->dwc; int ret; if (!dep->desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, dep->name); ret = -ESHUTDOWN; goto out; } /* we share one TRB for ep0/1 */ if (!list_empty(&dep->request_list)) { ret = -EBUSY; goto out; } dev_vdbg(dwc->dev, "queueing request %p to %s length %d, state '%s'\n", request, dep->name, request->length, dwc3_ep0_state_string(dwc->ep0state)); ret = __dwc3_gadget_ep0_queue(dep, req); out: return ret; }
static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { struct dwc3_ep *dep; enum usb_device_state state = dwc->gadget.state; u16 wLength; u16 wValue; if (state == USB_STATE_DEFAULT) return -EINVAL; wValue = le16_to_cpu(ctrl->wValue); wLength = le16_to_cpu(ctrl->wLength); if (wLength != 6) { dev_err(dwc->dev, "Set SEL should be 6 bytes, got %d\n", wLength); return -EINVAL; } /* * To handle Set SEL we need to receive 6 bytes from Host. So let's * queue a usb_request for 6 bytes. * * Remember, though, this controller can't handle non-wMaxPacketSize * aligned transfers on the OUT direction, so we queue a request for * wMaxPacketSize instead. */ dep = dwc->eps[0]; dwc->ep0_usb_req.dep = dep; dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket; dwc->ep0_usb_req.request.buf = dwc->setup_buf; dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl; return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req); }
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags) { struct dwc3_request *req = to_dwc3_request(request); struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3 *dwc = dep->dwc; unsigned long flags; int ret; spin_lock_irqsave(&dwc->lock, flags); if (!dep->endpoint.desc) { dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n", dep->name); ret = -ESHUTDOWN; goto out; } /* we share one TRB for ep0/1 */ if (!list_empty(&dep->pending_list)) { ret = -EBUSY; goto out; } ret = __dwc3_gadget_ep0_queue(dep, req); out: spin_unlock_irqrestore(&dwc->lock, flags); return ret; }
/* * ch 9.4.5 */ static int dwc3_ep0_handle_status(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { struct dwc3_ep *dep; u32 recip; u32 reg; u16 usb_status = 0; __le16 *response_pkt; recip = ctrl->bRequestType & USB_RECIP_MASK; switch (recip) { case USB_RECIP_DEVICE: /* * LTM will be set once we know how to set this in HW. */ usb_status |= dwc->gadget.is_selfpowered; if ((dwc->speed == DWC3_DSTS_SUPERSPEED) || (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) { reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (reg & DWC3_DCTL_INITU1ENA) usb_status |= 1 << USB_DEV_STAT_U1_ENABLED; if (reg & DWC3_DCTL_INITU2ENA) usb_status |= 1 << USB_DEV_STAT_U2_ENABLED; } break; case USB_RECIP_INTERFACE: /* * Function Remote Wake Capable D0 * Function Remote Wakeup D1 */ break; case USB_RECIP_ENDPOINT: dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); if (!dep) return -EINVAL; if (dep->flags & DWC3_EP_STALL) usb_status = 1 << USB_ENDPOINT_HALT; break; default: return -EINVAL; } response_pkt = (__le16 *) dwc->setup_buf; *response_pkt = cpu_to_le16(usb_status); dep = dwc->eps[0]; dwc->ep0_usb_req.dep = dep; dwc->ep0_usb_req.request.length = sizeof(*response_pkt); dwc->ep0_usb_req.request.buf = dwc->setup_buf; dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl; return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req); }
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags) { struct dwc3_request *req = to_dwc3_request(request); struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3 *dwc = dep->dwc; unsigned long flags; int ret; switch (dwc->ep0state) { case EP0_IN_DATA_PHASE: case EP0_IN_WAIT_GADGET: case EP0_IN_WAIT_NRDY: case EP0_IN_STATUS_PHASE: dep = dwc->eps[1]; break; case EP0_OUT_DATA_PHASE: case EP0_OUT_WAIT_GADGET: case EP0_OUT_WAIT_NRDY: case EP0_OUT_STATUS_PHASE: dep = dwc->eps[0]; break; default: return -EINVAL; } spin_lock_irqsave(&dwc->lock, flags); if (!dep->desc) { dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", request, dep->name); ret = -ESHUTDOWN; goto out; } /* we share one TRB for ep0/1 */ if (!list_empty(&dwc->eps[0]->request_list) || !list_empty(&dwc->eps[1]->request_list) || dwc->ep0_status_pending) { ret = -EBUSY; goto out; } dev_vdbg(dwc->dev, "queueing request %p to %s length %d, state '%s'\n", request, dep->name, request->length, dwc3_ep0_state_string(dwc->ep0state)); ret = __dwc3_gadget_ep0_queue(dep, req); out: spin_unlock_irqrestore(&dwc->lock, flags); return ret; }
/* * ch 9.4.5 */ static int dwc3_ep0_handle_status(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { struct dwc3_ep *dep; u32 recip; u16 usb_status = 0; __le16 *response_pkt; recip = ctrl->bRequestType & USB_RECIP_MASK; switch (recip) { case USB_RECIP_DEVICE: /* * We are self-powered. U1/U2/LTM will be set later * once we handle this states. RemoteWakeup is 0 on SS */ usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED; break; case USB_RECIP_INTERFACE: /* * Function Remote Wake Capable D0 * Function Remote Wakeup D1 */ break; case USB_RECIP_ENDPOINT: dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); if (!dep) return -EINVAL; if (dep->flags & DWC3_EP_STALL) usb_status = 1 << USB_ENDPOINT_HALT; break; default: return -EINVAL; }; response_pkt = (__le16 *) dwc->setup_buf; *response_pkt = cpu_to_le16(usb_status); dep = dwc->eps[0]; dwc->ep0_usb_req.dep = dep; dwc->ep0_usb_req.request.length = sizeof(*response_pkt); dwc->ep0_usb_req.request.dma = dwc->setup_buf_addr; dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl; return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req); }
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags) { struct dwc3_request *req = to_dwc3_request(request); struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3 *dwc = dep->dwc; unsigned long flags; int ret; spin_lock_irqsave(&dwc->lock, flags); if (!dep->endpoint.desc) { dwc3_trace(trace_dwc3_ep0, "trying to queue request %p to disabled %s", request, dep->name); ret = -ESHUTDOWN; goto out; } /* we share one TRB for ep0/1 */ if (!list_empty(&dep->request_list)) { ret = -EBUSY; goto out; } dwc3_trace(trace_dwc3_ep0, "queueing request %p to %s length %d state '%s'", request, dep->name, request->length, dwc3_ep0_state_string(dwc->ep0state)); ret = __dwc3_gadget_ep0_queue(dep, req); out: spin_unlock_irqrestore(&dwc->lock, flags); return ret; }