static int dwc3_ep0_handle_endpoint(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl, int set) { struct dwc3_ep *dep; enum usb_device_state state; u32 wValue; u32 wIndex; int ret; wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); state = dwc->gadget.state; switch (wValue) { case USB_ENDPOINT_HALT: dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); if (!dep) return -EINVAL; if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) break; ret = __dwc3_gadget_ep_set_halt(dep, set, true); if (ret) return -EINVAL; break; default: return -EINVAL; } return 0; }
/* * 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); }
/* * 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); }
static int dwc3_ep0_handle_feature(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl, int set) { struct dwc3_ep *dep; u32 recip; u32 wValue; u32 wIndex; #ifndef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE u32 reg; #endif int ret; enum usb_device_state state; wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); recip = ctrl->bRequestType & USB_RECIP_MASK; state = dwc->gadget.state; switch (recip) { case USB_RECIP_DEVICE: switch (wValue) { case USB_DEVICE_REMOTE_WAKEUP: break; /* * 9.4.1 says only only for SS, in AddressState only for * default control pipe */ case USB_DEVICE_U1_ENABLE: if (state != USB_STATE_CONFIGURED) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; /* see NEGATIVE RX DETECTION comment */ if (set && dwc->revision < DWC3_REVISION_230A) return 0; #ifndef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (set) reg |= DWC3_DCTL_INITU1ENA; else reg &= ~DWC3_DCTL_INITU1ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); #endif break; case USB_DEVICE_U2_ENABLE: if (state != USB_STATE_CONFIGURED) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; /* see NEGATIVE RX DETECTION comment */ if (set && dwc->revision < DWC3_REVISION_230A) return 0; #ifndef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (set) reg |= DWC3_DCTL_INITU2ENA; else reg &= ~DWC3_DCTL_INITU2ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); #endif break; case USB_DEVICE_LTM_ENABLE: return -EINVAL; break; case USB_DEVICE_TEST_MODE: if ((wIndex & 0xff) != 0) return -EINVAL; if (!set) return -EINVAL; dwc->test_mode_nr = wIndex >> 8; dwc->test_mode = true; break; default: return -EINVAL; } break; case USB_RECIP_INTERFACE: switch (wValue) { case USB_INTRF_FUNC_SUSPEND: if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) /* XXX enable Low power suspend */ ; if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) /* XXX enable remote wakeup */ ; break; default: return -EINVAL; } break; case USB_RECIP_ENDPOINT: switch (wValue) { case USB_ENDPOINT_HALT: dep = dwc3_wIndex_to_dep(dwc, wIndex); if (!dep) return -EINVAL; if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) break; ret = __dwc3_gadget_ep_set_halt(dep, set, true); if (ret) return -EINVAL; break; default: return -EINVAL; } break; default: return -EINVAL; }; return 0; }
static int dwc3_ep0_handle_feature(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl, int set) { struct dwc3_ep *dep; u32 recip; u32 wValue; u32 wIndex; u32 reg; int ret; wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); recip = ctrl->bRequestType & USB_RECIP_MASK; switch (recip) { case USB_RECIP_DEVICE: switch (wValue) { case USB_DEVICE_REMOTE_WAKEUP: break; /* * 9.4.1 says only only for SS, in AddressState only for * default control pipe */ case USB_DEVICE_U1_ENABLE: if (dwc->dev_state != DWC3_CONFIGURED_STATE) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (set) reg |= DWC3_DCTL_INITU1ENA; else reg &= ~DWC3_DCTL_INITU1ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); break; case USB_DEVICE_U2_ENABLE: if (dwc->dev_state != DWC3_CONFIGURED_STATE) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (set) reg |= DWC3_DCTL_INITU2ENA; else reg &= ~DWC3_DCTL_INITU2ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); break; case USB_DEVICE_LTM_ENABLE: return -EINVAL; break; case USB_DEVICE_TEST_MODE: if ((wIndex & 0xff) != 0) return -EINVAL; if (!set) return -EINVAL; dwc->test_mode_nr = wIndex >> 8; dwc->test_mode = true; break; default: return -EINVAL; } break; case USB_RECIP_INTERFACE: switch (wValue) { case USB_INTRF_FUNC_SUSPEND: if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) /* XXX enable Low power suspend */ ; if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) /* XXX enable remote wakeup */ ; break; default: return -EINVAL; } break; case USB_RECIP_ENDPOINT: switch (wValue) { case USB_ENDPOINT_HALT: dep = dwc3_wIndex_to_dep(dwc, wIndex); if (!dep) return -EINVAL; ret = __dwc3_gadget_ep_set_halt(dep, set); if (ret) return -EINVAL; break; default: return -EINVAL; } break; default: return -EINVAL; }; return 0; }
static int dwc3_ep0_handle_feature(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl, int set) { struct dwc3_ep *dep; u32 recip; u32 wValue; u32 wIndex; u32 reg; int ret; enum usb_device_state state; wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); recip = ctrl->bRequestType & USB_RECIP_MASK; state = dwc->gadget.state; switch (recip) { case USB_RECIP_DEVICE: switch (wValue) { case USB_DEVICE_REMOTE_WAKEUP: pr_debug("%s(): remote wakeup :%s\n", __func__, (set ? "enabled" : "disabled")); dwc->gadget.remote_wakeup = set; break; /* * 9.4.1 says only only for SS, in AddressState only for * default control pipe */ case USB_DEVICE_U1_ENABLE: if (state != USB_STATE_CONFIGURED) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; if (dwc->usb3_u1u2_disable && !enable_dwc3_u1u2) return -EINVAL; reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (set) reg |= DWC3_DCTL_INITU1ENA; else reg &= ~DWC3_DCTL_INITU1ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); break; case USB_DEVICE_U2_ENABLE: if (state != USB_STATE_CONFIGURED) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; if (dwc->usb3_u1u2_disable && !enable_dwc3_u1u2) return -EINVAL; reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (set) reg |= DWC3_DCTL_INITU2ENA; else reg &= ~DWC3_DCTL_INITU2ENA; dwc3_writel(dwc->regs, DWC3_DCTL, reg); break; case USB_DEVICE_LTM_ENABLE: return -EINVAL; break; case USB_DEVICE_TEST_MODE: if ((wIndex & 0xff) != 0) return -EINVAL; if (!set) return -EINVAL; dwc->test_mode_nr = wIndex >> 8; dwc->test_mode = true; break; default: return -EINVAL; } break; case USB_RECIP_INTERFACE: switch (wValue) { case USB_INTRF_FUNC_SUSPEND: if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) /* XXX enable Low power suspend */ ; if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) /* XXX enable remote wakeup */ ; ret = dwc3_ep0_delegate_req(dwc, ctrl); if (ret) return ret; break; default: return -EINVAL; } break; case USB_RECIP_ENDPOINT: switch (wValue) { case USB_ENDPOINT_HALT: dep = dwc3_wIndex_to_dep(dwc, wIndex); if (!dep) return -EINVAL; if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) break; ret = __dwc3_gadget_ep_set_halt(dep, set); if (ret) return -EINVAL; break; default: return -EINVAL; } break; default: return -EINVAL; }; return 0; }
static int dwc3_ep0_handle_feature(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl, int set) { struct dwc3_ep *dep; u32 recip; u32 wValue; u32 wIndex; u32 reg; int ret; u32 mode; wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); recip = ctrl->bRequestType & USB_RECIP_MASK; switch (recip) { case USB_RECIP_DEVICE: /* * 9.4.1 says only only for SS, in AddressState only for * default control pipe */ switch (wValue) { case USB_DEVICE_U1_ENABLE: case USB_DEVICE_U2_ENABLE: case USB_DEVICE_LTM_ENABLE: if (dwc->dev_state != DWC3_CONFIGURED_STATE) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; } /* XXX add U[12] & LTM */ switch (wValue) { case USB_DEVICE_REMOTE_WAKEUP: break; case USB_DEVICE_U1_ENABLE: break; case USB_DEVICE_U2_ENABLE: break; case USB_DEVICE_LTM_ENABLE: break; case USB_DEVICE_TEST_MODE: if ((wIndex & 0xff) != 0) return -EINVAL; if (!set) return -EINVAL; mode = wIndex >> 8; reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_TSTCTRL_MASK; switch (mode) { case TEST_J: case TEST_K: case TEST_SE0_NAK: case TEST_PACKET: case TEST_FORCE_EN: reg |= mode << 1; break; default: return -EINVAL; } dwc3_writel(dwc->regs, DWC3_DCTL, reg); break; default: return -EINVAL; } break; case USB_RECIP_INTERFACE: switch (wValue) { case USB_INTRF_FUNC_SUSPEND: if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) /* XXX enable Low power suspend */ ; if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) /* XXX enable remote wakeup */ ; break; default: return -EINVAL; } break; case USB_RECIP_ENDPOINT: switch (wValue) { case USB_ENDPOINT_HALT: dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); if (!dep) return -EINVAL; ret = __dwc3_gadget_ep_set_halt(dep, set); if (ret) return -EINVAL; break; default: return -EINVAL; } break; default: return -EINVAL; }; dwc->ep0state = EP0_IN_WAIT_NRDY; return 0; }