// SPDX-License-Identifier: GPL-2.0 /* * MUSB OTG peripheral driver ep0 handling * * Copyright 2005 Mentor Graphics Corporation * Copyright (C) 2005-2006 by Texas Instruments * Copyright (C) 2006-2007 Nokia Corporation * Copyright (C) 2008-2009 MontaVista Software, Inc. <[email protected]> */ #include <linux/kernel.h> #include <linux/list.h> #include <linux/timer.h> #include <linux/spinlock.h> #include <linux/device.h> #include <linux/interrupt.h> #include "musb_core.h" /* ep0 is always musb->endpoints[0].ep_in */ #define next_ep0_request(musb) … /* * locking note: we use only the controller lock, for simpler correctness. * It's always held with IRQs blocked. * * It protects the ep0 request queue as well as ep0_state, not just the * controller and indexed registers. And that lock stays held unless it * needs to be dropped to allow reentering this driver ... like upcalls to * the gadget driver, or adjusting endpoint halt status. */ static char *decode_ep0stage(u8 stage) { … } /* handle a standard GET_STATUS request * Context: caller holds controller lock */ static int service_tx_status_request( struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) { … } /* * handle a control-IN request, the end0 buffer contains the current request * that is supposed to be a standard control request. Assumes the fifo to * be at least 2 bytes long. * * @return 0 if the request was NOT HANDLED, * < 0 when error * > 0 when the request is processed * * Context: caller holds controller lock */ static int service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) { … } /* * Context: caller holds controller lock */ static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req) { … } /* * Tries to start B-device HNP negotiation if enabled via sysfs */ static inline void musb_try_b_hnp_enable(struct musb *musb) { … } /* * Handle all control requests with no DATA stage, including standard * requests such as: * USB_REQ_SET_CONFIGURATION, USB_REQ_SET_INTERFACE, unrecognized * always delegated to the gadget driver * USB_REQ_SET_ADDRESS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE * always handled here, except for class/vendor/... features * * Context: caller holds controller lock */ static int service_zero_data_request(struct musb *musb, struct usb_ctrlrequest *ctrlrequest) __releases(musb->lock) __acquires(musb->lock) { … } /* we have an ep0out data packet * Context: caller holds controller lock */ static void ep0_rxstate(struct musb *musb) { … } /* * transmitting to the host (IN), this code might be called from IRQ * and from kernel thread. * * Context: caller holds controller lock */ static void ep0_txstate(struct musb *musb) { … } /* * Read a SETUP packet (struct usb_ctrlrequest) from the hardware. * Fields are left in USB byte-order. * * Context: caller holds controller lock. */ static void musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req) { … } static int forward_to_driver(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) __releases(musb->lock) __acquires(musb->lock) { … } /* * Handle peripheral ep0 interrupt * * Context: irq handler; we won't re-enter the driver that way. */ irqreturn_t musb_g_ep0_irq(struct musb *musb) { … } static int musb_g_ep0_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { … } static int musb_g_ep0_disable(struct usb_ep *e) { … } static int musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags) { … } static int musb_g_ep0_dequeue(struct usb_ep *ep, struct usb_request *req) { … } static int musb_g_ep0_halt(struct usb_ep *e, int value) { … } const struct usb_ep_ops musb_g_ep0_ops = …;