state = pdev->gadget.state;
speed = pdev->gadget.speed;
switch (le16_to_cpu(ctrl->wValue)) { case USB_DEVICE_REMOTE_WAKEUP:
pdev->may_wakeup = !!set;
trace_cdnsp_may_wakeup(set); break; case USB_DEVICE_U1_ENABLE: if (state != USB_STATE_CONFIGURED || speed < USB_SPEED_SUPER) return -EINVAL;
pdev->u1_allowed = !!set;
trace_cdnsp_u1(set); break; case USB_DEVICE_U2_ENABLE: if (state != USB_STATE_CONFIGURED || speed < USB_SPEED_SUPER) return -EINVAL;
pdev->u2_allowed = !!set;
trace_cdnsp_u2(set); break; case USB_DEVICE_LTM_ENABLE: return -EINVAL; case USB_DEVICE_TEST_MODE: if (state != USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH) return -EINVAL;
tmode = le16_to_cpu(ctrl->wIndex);
if (!set || (tmode & 0xff) != 0) return -EINVAL;
tmode = tmode >> 8;
if (tmode > USB_TEST_FORCE_ENABLE || tmode < USB_TEST_J) return -EINVAL;
pdev->test_mode = tmode;
/* * Test mode must be set before Status Stage but controller * will start testing sequence after Status Stage.
*/
cdnsp_enter_test_mode(pdev); break; default: return -EINVAL;
}
return 0;
}
staticint cdnsp_ep0_handle_feature_intf(struct cdnsp_device *pdev, struct usb_ctrlrequest *ctrl, int set)
{
u16 wValue, wIndex; int ret;
switch (wValue) { case USB_INTRF_FUNC_SUSPEND:
ret = cdnsp_ep0_delegate_req(pdev, ctrl); if (ret) return ret;
/* * Remote wakeup is enabled when any function within a device * is enabled for function remote wakeup.
*/ if (wIndex & USB_INTRF_FUNC_SUSPEND_RW)
pdev->may_wakeup++; else if (pdev->may_wakeup > 0)
pdev->may_wakeup--;
if (wLength != 6) {
dev_err(pdev->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.
*/
pdev->ep0_preq.request.length = 6;
pdev->ep0_preq.request.buf = pdev->setup_buf;
staticint cdnsp_ep0_std_request(struct cdnsp_device *pdev, struct usb_ctrlrequest *ctrl)
{ int ret;
switch (ctrl->bRequest) { case USB_REQ_GET_STATUS:
ret = cdnsp_ep0_handle_status(pdev, ctrl); break; case USB_REQ_CLEAR_FEATURE:
ret = cdnsp_ep0_handle_feature(pdev, ctrl, 0); break; case USB_REQ_SET_FEATURE:
ret = cdnsp_ep0_handle_feature(pdev, ctrl, 1); break; case USB_REQ_SET_ADDRESS:
ret = cdnsp_ep0_set_address(pdev, ctrl); break; case USB_REQ_SET_CONFIGURATION:
ret = cdnsp_ep0_set_config(pdev, ctrl); break; case USB_REQ_SET_SEL:
ret = cdnsp_ep0_set_sel(pdev, ctrl); break; case USB_REQ_SET_ISOCH_DELAY:
ret = cdnsp_ep0_set_isoch_delay(pdev, ctrl); break; default:
ret = cdnsp_ep0_delegate_req(pdev, ctrl); break;
}
return ret;
}
void cdnsp_setup_analyze(struct cdnsp_device *pdev)
{ struct usb_ctrlrequest *ctrl = &pdev->setup; struct cdnsp_ep *pep; int ret = -EINVAL;
u16 len;
trace_cdnsp_ctrl_req(ctrl);
if (!pdev->gadget_driver) goto out;
if (pdev->gadget.state == USB_STATE_NOTATTACHED) {
dev_err(pdev->dev, "ERR: Setup detected in unattached state\n"); goto out;
}
pep = &pdev->eps[0];
/* Restore the ep0 to Stopped/Running state. */ if (pep->ep_state & EP_HALTED) { if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_HALTED)
cdnsp_halt_endpoint(pdev, pep, 0);
/* * Halt Endpoint Command for SSP2 for ep0 preserve current * endpoint state and driver has to synchronize the * software endpoint state with endpoint output context * state.
*/
pep->ep_state &= ~EP_HALTED;
pep->ep_state |= EP_STOPPED;
}
/* * Finishing previous SETUP transfer by removing request from * list and informing upper layer
*/ if (!list_empty(&pdev->eps[0].pending_list)) { struct cdnsp_request *req;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.