// SPDX-License-Identifier: GPL-2.0
/**
* udc.c - Core UDC Framework
*
* Copyright (C) 2010 Texas Instruments
* Author: Felipe Balbi <balbi@ti.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/err.h>
#include <linux/dma-mapping.h>
#include <linux/sched/task_stack.h>
#include <linux/workqueue.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb.h>
#include "trace.h"
/**
* struct usb_udc - describes one usb device controller
* @driver - the gadget driver pointer. For use by the class code
* @dev - the child device to the actual controller
* @gadget - the gadget. For use by the class code
* @list - for use by the udc class driver
* @vbus - for udcs who care about vbus status, this value is real vbus status;
* for udcs who do not care about vbus status, this value is always true
*
* This represents the internal data structure which is used by the UDC-class
* to hold information about udc driver and gadget together.
*/
struct usb_udc {
struct usb_gadget_driver *driver;
struct usb_gadget *gadget;
struct device dev;
struct list_head list;
bool vbus;
};
static struct class *udc_class;
static LIST_HEAD(udc_list);
static LIST_HEAD(gadget_driver_pending_list);
static DEFINE_MUTEX(udc_lock);
static int udc_bind_to_driver(struct usb_udc *udc,
struct usb_gadget_driver *driver);
/* ------------------------------------------------------------------------- */
/**
* usb_ep_set_maxpacket_limit - set maximum packet size limit for endpoint
* @ep:the endpoint being configured
* @maxpacket_limit:value of maximum packet size limit
*
* This function should be used only in UDC drivers to initialize endpoint
* (usually in probe function).
*/
void usb_ep_set_maxpacket_limit(struct usb_ep *ep,
unsigned maxpacket_limit)
{
ep->maxpacket_limit = maxpacket_limit;
ep->maxpacket = maxpacket_limit;
trace_usb_ep_set_maxpacket_limit(ep, 0);
}
EXPORT_SYMBOL_GPL(usb_ep_set_maxpacket_limit);
/**
* usb_ep_enable - configure endpoint, making it usable
* @ep:the endpoint being configured. may not be the endpoint named "ep0".
* drivers discover endpoints through the ep_list of a usb_gadget.
*
* When configurations are set, or when interface settings change, the driver
* will enable or disable the relevant endpoints. while it is enabled, an
* endpoint may be used for i/o until the driver receives a disconnect() from
* the host or until the endpoint is disabled.
*
* the ep0 implementation (which calls this routine) must ensure that the
* hardware capabilities of each endpoint match the descriptor provided
* for it. for example, an endpoint named "ep2in-bulk" would be usable
* for interrupt transfers as well as bulk, but it likely couldn't be used
* for iso transfers or for endpoint 14. some endpoints are fully
* configurable, with more generic names like "ep-a". (remember that for
* USB, "in" means "towards the USB master".)
*
* This routine must be called in process context.
*
* returns zero, or a negative error code.
*/
int usb_ep_enable(struct usb_ep *ep)
{
int ret = 0;
if (ep->enabled)
goto out;
ret = ep->ops->enable(ep, ep->desc);
if (ret)
goto out;
ep->enabled = true;
out:
trace_usb_ep_enable(ep, ret);
return ret;
}
EXPORT_SYMBOL_GPL(usb_ep_enable);
/**
* usb_ep_disable - endpoint is no longer usable
* @ep:the endpoint being unconfigured. may not be the endpoint named "ep0".
*
* no other task may be using this endpoint when this is called.
* any pending and uncompleted requests will complete with status
* indicating disconnect (-ESHUTDOWN) before this call returns.
* gadget drivers must call usb_ep_enable() again before queueing
* requests to the endpoint.
*
* This routine must be called in process context.
*
* returns zero, or a negative error code.
*/
int usb_ep_disable(struct usb_ep *ep)
{
int ret = 0;
if (!ep->enabled)
goto out;
ret = ep->ops->disable(ep);
if (ret)
goto out;
ep->enabled = false;
out:
trace_usb_ep_disable(ep, ret);
return ret;
}
EXPORT_SYMBOL_GPL(usb_ep_disable);
/**
* usb_ep_alloc_request - allocate a request object to use with this e
|