static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { u32 cfg; int ret; dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (dwc->dev_state) { case DWC3_DEFAULT_STATE: return -EINVAL; break; case DWC3_ADDRESS_STATE: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (!ret && cfg) dwc->dev_state = DWC3_CONFIGURED_STATE; break; case DWC3_CONFIGURED_STATE: ret = dwc3_ep0_delegate_req(dwc, ctrl); if (!cfg) dwc->dev_state = DWC3_ADDRESS_STATE; break; default: ret = -EINVAL; } return ret; }
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { u32 cfg; int ret; dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (dwc->dev_state) { case DWC3_DEFAULT_STATE: return -EINVAL; break; case DWC3_ADDRESS_STATE: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { dwc->dev_state = DWC3_CONFIGURED_STATE; dwc->resize_fifos = true; dev_dbg(dwc->dev, "resize fifos flag SET\n"); } break; case DWC3_CONFIGURED_STATE: ret = dwc3_ep0_delegate_req(dwc, ctrl); if (!cfg) dwc->dev_state = DWC3_ADDRESS_STATE; break; default: ret = -EINVAL; } return ret; }
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { enum usb_device_state state = dwc->gadget.state; u32 cfg; int ret; u32 reg; dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (state) { case USB_STATE_DEFAULT: return -EINVAL; break; case USB_STATE_ADDRESS: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); if (dwc->ssphy_clear_auto_suspend_on_disconnect) { reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_SUSPHY; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); } if (!dwc->usb3_u1u2_disable || enable_dwc3_u1u2) { /* * Enable transition to U1/U2 state when * nothing is pending from application. */ reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); dwc3_writel(dwc->regs, DWC3_DCTL, reg); } dwc->resize_fifos = true; dev_dbg(dwc->dev, "resize fifos flag SET\n"); } break; case USB_STATE_CONFIGURED: ret = dwc3_ep0_delegate_req(dwc, ctrl); if (!cfg) usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); break; default: ret = -EINVAL; } return ret; }
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { enum usb_device_state state = dwc->gadget.state; u32 cfg; int ret; u32 reg; dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (state) { case USB_STATE_DEFAULT: return -EINVAL; break; case USB_STATE_ADDRESS: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { /* * only change state if set_config has already * been processed. If gadget driver returns * USB_GADGET_DELAYED_STATUS, we will wait * to change the state on the next usb_ep_queue() */ if (ret == 0) usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); /* * Enable transition to U1/U2 state when * nothing is pending from application. */ reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc->resize_fifos = true; dwc3_trace(trace_dwc3_ep0, "resize FIFOs flag SET"); } break; case USB_STATE_CONFIGURED: ret = dwc3_ep0_delegate_req(dwc, ctrl); if (!cfg && !ret) usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); break; default: ret = -EINVAL; } return ret; }
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { enum usb_device_state state = dwc->gadget.state; u32 cfg; int ret; #ifndef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE u32 reg; #endif dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (state) { case USB_STATE_DEFAULT: return -EINVAL; break; case USB_STATE_ADDRESS: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); #ifndef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE /* * Enable transition to U1/U2 state when * nothing is pending from application. */ reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); dwc3_writel(dwc->regs, DWC3_DCTL, reg); #endif dwc->resize_fifos = true; dev_dbg(dwc->dev, "resize fifos flag SET\n"); } break; case USB_STATE_CONFIGURED: ret = dwc3_ep0_delegate_req(dwc, ctrl); if (!cfg) usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); break; default: ret = -EINVAL; } return ret; }
static int dwc3_ep0_set_interface(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { u32 alt_setting; enum usb_device_state state = dwc->gadget.state; int ret; alt_setting = le16_to_cpu(ctrl->wValue); ret = dwc3_ep0_delegate_req(dwc, ctrl); switch (state) { case USB_STATE_CONFIGURED: /* if the alt_setting matches and the alt_setting is non zero */ if (alt_setting && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { dwc->resize_fifos = true; dev_dbg(dwc->dev, "resize fifos flag SET\n"); } break; default: dev_err(dwc->dev, "default case\n"); } return ret; }
static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { int ret; switch (ctrl->bRequest) { case USB_REQ_GET_STATUS: ret = dwc3_ep0_handle_status(dwc, ctrl); break; case USB_REQ_CLEAR_FEATURE: ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); break; case USB_REQ_SET_FEATURE: ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); break; case USB_REQ_SET_ADDRESS: ret = dwc3_ep0_set_address(dwc, ctrl); break; case USB_REQ_SET_CONFIGURATION: ret = dwc3_ep0_set_config(dwc, ctrl); break; case USB_REQ_SET_SEL: ret = dwc3_ep0_set_sel(dwc, ctrl); break; case USB_REQ_SET_ISOCH_DELAY: ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); break; default: ret = dwc3_ep0_delegate_req(dwc, ctrl); break; } return ret; }
static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct usb_ctrlrequest *ctrl = dwc->ctrl_req; int ret = -EINVAL; u32 len; if (!dwc->gadget_driver) goto out; len = le16_to_cpu(ctrl->wLength); if (!len) { dwc->three_stage_setup = false; dwc->ep0_expect_in = false; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; } else { dwc->three_stage_setup = true; dwc->ep0_expect_in = !!(ctrl->bRequestType & USB_DIR_IN); dwc->ep0_next_event = DWC3_EP0_NRDY_DATA; } if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) ret = dwc3_ep0_std_request(dwc, ctrl); else ret = dwc3_ep0_delegate_req(dwc, ctrl); if (ret == USB_GADGET_DELAYED_STATUS) dwc->delayed_status = true; out: if (ret < 0) dwc3_ep0_stall_and_restart(dwc); }
static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { struct usb_ctrlrequest *ctrl = dwc->ctrl_req; int ret; u32 len; if (!dwc->gadget_driver) goto err; len = le16_to_cpu(ctrl->wLength); if (!len) { dwc->ep0state = EP0_IN_WAIT_GADGET; dwc->three_stage_setup = 0; } else { dwc->three_stage_setup = 1; if (ctrl->bRequestType & USB_DIR_IN) dwc->ep0state = EP0_IN_DATA_PHASE; else dwc->ep0state = EP0_OUT_DATA_PHASE; } if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) ret = dwc3_ep0_std_request(dwc, ctrl); else ret = dwc3_ep0_delegate_req(dwc, ctrl); if (ret >= 0) return; err: dwc3_ep0_stall_and_restart(dwc); }
static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { int ret; switch (ctrl->bRequest) { case USB_REQ_GET_STATUS: dev_vdbg(dwc->dev, "USB_REQ_GET_STATUS\n"); ret = dwc3_ep0_handle_status(dwc, ctrl); break; case USB_REQ_CLEAR_FEATURE: dev_vdbg(dwc->dev, "USB_REQ_CLEAR_FEATURE\n"); ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); break; case USB_REQ_SET_FEATURE: dev_vdbg(dwc->dev, "USB_REQ_SET_FEATURE\n"); ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); break; case USB_REQ_SET_ADDRESS: dev_vdbg(dwc->dev, "USB_REQ_SET_ADDRESS\n"); ret = dwc3_ep0_set_address(dwc, ctrl); break; case USB_REQ_SET_CONFIGURATION: dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n"); ret = dwc3_ep0_set_config(dwc, ctrl); break; default: dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); ret = dwc3_ep0_delegate_req(dwc, ctrl); break; }; return ret; }
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { u32 cfg; int ret; #ifndef CONFIG_PANTECH_SIO_TEMP u32 reg; #endif dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (dwc->dev_state) { case DWC3_DEFAULT_STATE: return -EINVAL; break; case DWC3_ADDRESS_STATE: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { dwc->dev_state = DWC3_CONFIGURED_STATE; #ifndef CONFIG_PANTECH_SIO_TEMP /* * Enable transition to U1/U2 state when * nothing is pending from application. */ reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); dwc3_writel(dwc->regs, DWC3_DCTL, reg); #endif dwc->resize_fifos = true; dev_dbg(dwc->dev, "resize fifos flag SET\n"); } break; case DWC3_CONFIGURED_STATE: ret = dwc3_ep0_delegate_req(dwc, ctrl); if (!cfg) dwc->dev_state = DWC3_ADDRESS_STATE; break; default: ret = -EINVAL; } return ret; }
static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { int ret; #ifdef CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT u16 w_value = le16_to_cpu(ctrl->wValue); #endif switch (ctrl->bRequest) { case USB_REQ_GET_STATUS: dev_vdbg(dwc->dev, "USB_REQ_GET_STATUS\n"); ret = dwc3_ep0_handle_status(dwc, ctrl); break; case USB_REQ_CLEAR_FEATURE: dev_vdbg(dwc->dev, "USB_REQ_CLEAR_FEATURE\n"); ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); break; case USB_REQ_SET_FEATURE: dev_vdbg(dwc->dev, "USB_REQ_SET_FEATURE\n"); ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); break; case USB_REQ_SET_ADDRESS: dev_vdbg(dwc->dev, "USB_REQ_SET_ADDRESS\n"); ret = dwc3_ep0_set_address(dwc, ctrl); #ifdef CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT dwc->dotg->charger->vzw_usb_config_state = VZW_USB_STATE_CONNECTED; queue_delayed_work(system_nrt_wq, dwc->dotg->charger->drv_check_state_wq, 0); #endif break; case USB_REQ_SET_CONFIGURATION: dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n"); #ifdef CONFIG_DWC3_MSM_BC_12_VZW_SUPPORT if (w_value) { dwc->dotg->charger->vzw_usb_config_state = VZW_USB_STATE_CONFIGURED; queue_delayed_work(system_nrt_wq, dwc->dotg->charger->drv_check_state_wq, 0); } #endif ret = dwc3_ep0_set_config(dwc, ctrl); break; case USB_REQ_SET_SEL: dev_vdbg(dwc->dev, "USB_REQ_SET_SEL\n"); ret = dwc3_ep0_set_sel(dwc, ctrl); break; case USB_REQ_SET_ISOCH_DELAY: dev_vdbg(dwc->dev, "USB_REQ_SET_ISOCH_DELAY\n"); ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); break; default: dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); ret = dwc3_ep0_delegate_req(dwc, ctrl); break; }; return ret; }
static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { int ret; switch (ctrl->bRequest) { case USB_REQ_GET_STATUS: dwc3_trace(trace_dwc3_ep0, "USB_REQ_GET_STATUS\n"); ret = dwc3_ep0_handle_status(dwc, ctrl); break; case USB_REQ_CLEAR_FEATURE: dwc3_trace(trace_dwc3_ep0, "USB_REQ_CLEAR_FEATURE\n"); ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); break; case USB_REQ_SET_FEATURE: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_FEATURE\n"); ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); break; case USB_REQ_SET_ADDRESS: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ADDRESS\n"); ret = dwc3_ep0_set_address(dwc, ctrl); break; case USB_REQ_SET_CONFIGURATION: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_CONFIGURATION\n"); ret = dwc3_ep0_set_config(dwc, ctrl); break; case USB_REQ_SET_SEL: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_SEL\n"); ret = dwc3_ep0_set_sel(dwc, ctrl); break; case USB_REQ_SET_ISOCH_DELAY: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY\n"); ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); break; case USB_REQ_SET_INTERFACE: dev_vdbg(dwc->dev, "USB_REQ_SET_INTERFACE\n"); dwc->start_config_issued = false; /* Fall through */ default: dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver\n"); ret = dwc3_ep0_delegate_req(dwc, ctrl); break; } return ret; }
static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { int ret; switch (ctrl->bRequest) { case USB_REQ_GET_STATUS: dwc3_trace(trace_dwc3_ep0, "USB_REQ_GET_STATUS"); ret = dwc3_ep0_handle_status(dwc, ctrl); break; case USB_REQ_CLEAR_FEATURE: dwc3_trace(trace_dwc3_ep0, "USB_REQ_CLEAR_FEATURE"); ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); break; case USB_REQ_SET_FEATURE: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_FEATURE"); ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); break; case USB_REQ_SET_ADDRESS: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ADDRESS"); ret = dwc3_ep0_set_address(dwc, ctrl); break; case USB_REQ_SET_CONFIGURATION: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_CONFIGURATION"); ret = dwc3_ep0_set_config(dwc, ctrl); break; case USB_REQ_SET_SEL: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_SEL"); ret = dwc3_ep0_set_sel(dwc, ctrl); break; case USB_REQ_SET_ISOCH_DELAY: dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY"); ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); break; default: dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver"); ret = dwc3_ep0_delegate_req(dwc, ctrl); break; } return ret; }
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { enum usb_device_state state = dwc->gadget.state; u32 cfg; int ret; #ifndef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE u32 reg; #endif dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); switch (state) { case USB_STATE_DEFAULT: return -EINVAL; break; case USB_STATE_ADDRESS: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { /* * only change state if set_config has already * been processed. If gadget driver returns * USB_GADGET_DELAYED_STATUS, we will wait * to change the state on the next usb_ep_queue() */ if (ret == 0) usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); #ifndef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE /* * NEGATIVE RX DETECTION * Some host controllers (e.g. Intel) perform far-end * receiver termination _negative_ detection while link * is in U2 state. Synopsys PIPE PHY considers this * signalling as U2 LFPS exit, moves to Recovery state * and waits for training sequence which never comes. * This finally leads to reconnection. Starting from * DWC3 core 2.30a, GCTL register has bit U2EXIT_LFPS, * which improves interoperability with such HCs. */ if (dwc->revision >= DWC3_REVISION_230A) { /* * Enable transition to U1/U2 state when * nothing is pending from application. */ reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); dwc3_writel(dwc->regs, DWC3_DCTL, reg); } #endif dwc->resize_fifos = true; dev_dbg(dwc->dev, "resize fifos flag SET\n"); } break; case USB_STATE_CONFIGURED: ret = dwc3_ep0_delegate_req(dwc, ctrl); if (!cfg && !ret) usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); break; default: ret = -EINVAL; } return ret; }
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; }
/* * ch 9.4.5 */ static int dwc3_ep0_handle_status(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { int ret; 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->is_selfpowered << USB_DEVICE_SELF_POWERED; if (dwc->speed == DWC3_DSTS_SUPERSPEED) { 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; } else { usb_status |= dwc->gadget.remote_wakeup << USB_DEVICE_REMOTE_WAKEUP; } break; case USB_RECIP_INTERFACE: /* * Function Remote Wake Capable D0 * Function Remote Wakeup D1 */ ret = dwc3_ep0_delegate_req(dwc, ctrl); if (ret) return ret; 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); }