switch (recip) { case USB_RECIP_DEVICE:
status = pdev->gadget.is_selfpowered;
status |= pdev->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; break; case USB_RECIP_INTERFACE: return cdns2_ep0_delegate_req(pdev); case USB_RECIP_ENDPOINT:
ep_sts = cdns2_w_index_to_ep_index(le16_to_cpu(ctrl->wIndex));
pep = &pdev->eps[ep_sts];
if (pep->ep_state & EP_STALLED)
status = BIT(USB_ENDPOINT_HALT); break; default: return -EINVAL;
}
staticint cdns2_ep0_handle_feature_device(struct cdns2_device *pdev, struct usb_ctrlrequest *ctrl, int set)
{ enum usb_device_state state; enum usb_device_speed speed; int ret = 0;
u32 wValue;
u16 tmode;
wValue = le16_to_cpu(ctrl->wValue);
state = pdev->gadget.state;
speed = pdev->gadget.speed;
switch (wValue) { case USB_DEVICE_REMOTE_WAKEUP:
pdev->may_wakeup = !!set; break; 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 >>= 8; switch (tmode) { case USB_TEST_J: case USB_TEST_K: case USB_TEST_SE0_NAK: case USB_TEST_PACKET: /* * The USBHS controller automatically handles the * Set_Feature(testmode) request. Standard test modes * that use values of test mode selector from * 01h to 04h (Test_J, Test_K, Test_SE0_NAK, * Test_Packet) are supported by the * controller(HS - ack, FS - stall).
*/ break; default:
ret = -EINVAL;
} break; default:
ret = -EINVAL;
}
return ret;
}
staticint cdns2_ep0_handle_feature_intf(struct cdns2_device *pdev, struct usb_ctrlrequest *ctrl, int set)
{ int ret = 0;
u32 wValue;
wValue = le16_to_cpu(ctrl->wValue);
switch (wValue) { case USB_INTRF_FUNC_SUSPEND: break; default:
ret = -EINVAL;
}
switch (ctrl->bRequest) { case USB_REQ_SET_ADDRESS:
ret = cdns2_req_ep0_set_address(pdev,
le16_to_cpu(ctrl->wValue)); break; case USB_REQ_SET_CONFIGURATION:
ret = cdns2_req_ep0_set_configuration(pdev, ctrl); break; case USB_REQ_GET_STATUS:
ret = cdns2_req_ep0_handle_status(pdev, ctrl); break; case USB_REQ_CLEAR_FEATURE:
ret = cdns2_req_ep0_handle_feature(pdev, ctrl, 0); break; case USB_REQ_SET_FEATURE:
ret = cdns2_req_ep0_handle_feature(pdev, ctrl, 1); break; default:
ret = cdns2_ep0_delegate_req(pdev); break;
}
void cdns2_handle_setup_packet(struct cdns2_device *pdev)
{ struct usb_ctrlrequest *ctrl = &pdev->setup; struct cdns2_endpoint *pep = &pdev->eps[0]; struct cdns2_request *preq; int ret = 0;
u16 len;
u8 reg; int i;
writeb(EP0CS_CHGSET, &pdev->ep0_regs->cs);
for (i = 0; i < 8; i++)
((u8 *)&pdev->setup)[i] = readb(&pdev->ep0_regs->setupdat[i]);
/* * If SETUP packet was modified while reading just simple ignore it. * The new one will be handled latter.
*/ if (cdns2_check_new_setup(pdev)) {
trace_cdns2_ep0_setup("overridden"); return;
}
trace_cdns2_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");
ret = -EINVAL; goto out;
}
pep = &pdev->eps[0];
/* Halt for Ep0 is cleared automatically when SETUP packet arrives. */
pep->ep_state &= ~EP_STALLED;
if (!list_empty(&pep->pending_list)) {
preq = cdns2_next_preq(&pep->pending_list);
cdns2_gadget_giveback(pep, preq, -ECONNRESET);
}
len = le16_to_cpu(ctrl->wLength); if (len)
pdev->ep0_stage = CDNS2_DATA_STAGE; else
pdev->ep0_stage = CDNS2_STATUS_STAGE;
pep->dir = ctrl->bRequestType & USB_DIR_IN;
/* * SET_ADDRESS request is acknowledged automatically by controller and * in the worse case driver may not notice this request. To check * whether this request has been processed driver can use * fnaddr register.
*/
reg = readb(&pdev->usb_regs->fnaddr); if (pdev->setup.bRequest != USB_REQ_SET_ADDRESS &&
pdev->dev_address != reg)
cdns2_req_ep0_set_address(pdev, reg);
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
ret = cdns2_ep0_std_request(pdev); else
ret = cdns2_ep0_delegate_req(pdev);
if (ret == USB_GADGET_DELAYED_STATUS) {
trace_cdns2_ep0_status_stage("delayed"); return;
}
/* * Function shouldn't be called by gadget driver, * endpoint 0 is allways active.
*/ staticint cdns2_gadget_ep0_enable(struct usb_ep *ep, conststruct usb_endpoint_descriptor *desc)
{ return -EINVAL;
}
/* * Function shouldn't be called by gadget driver, * endpoint 0 is allways active.
*/ staticint cdns2_gadget_ep0_disable(struct usb_ep *ep)
{ return -EINVAL;
}
/* Cancel the request if controller receive new SETUP packet. */ if (cdns2_check_new_setup(pdev)) {
trace_cdns2_ep0_setup("overridden");
spin_unlock_irqrestore(&pdev->lock, flags); return -ECONNRESET;
}
/* Send STATUS stage. Should be called only for SET_CONFIGURATION. */ if (pdev->ep0_stage == CDNS2_STATUS_STAGE) {
cdns2_status_stage(pdev);
/* * Since there is no completion interrupt for status stage, * it needs to call ->completion in software after * cdns2_gadget_ep0_queue is back.
*/
queue_work(system_freezable_wq, &pdev->pending_status_wq); return 0;
}
if (!list_empty(&pep->pending_list)) {
trace_cdns2_ep0_setup("pending");
dev_err(pdev->dev, "can't handle multiple requests for ep0\n");
spin_unlock_irqrestore(&pdev->lock, flags); return -EBUSY;
}
ret = usb_gadget_map_request_by_dev(pdev->dev, request, pep->dir); if (ret) {
spin_unlock_irqrestore(&pdev->lock, flags);
dev_err(pdev->dev, "failed to map request\n"); return -EINVAL;
}
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.