linux/drivers/usb/gadget/composite.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * composite.c - infrastructure for Composite USB Gadgets
 *
 * Copyright (C) 2006-2008 David Brownell
 */

/* #define VERBOSE_DEBUG */

#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/utsname.h>
#include <linux/bitfield.h>
#include <linux/uuid.h>

#include <linux/usb/composite.h>
#include <linux/usb/otg.h>
#include <linux/usb/webusb.h>
#include <asm/unaligned.h>

#include "u_os_desc.h"

/**
 * struct usb_os_string - represents OS String to be reported by a gadget
 * @bLength: total length of the entire descritor, always 0x12
 * @bDescriptorType: USB_DT_STRING
 * @qwSignature: the OS String proper
 * @bMS_VendorCode: code used by the host for subsequent requests
 * @bPad: not used, must be zero
 */
struct usb_os_string {} __packed;

/*
 * The code in this file is utility code, used to build a gadget driver
 * from one or more "function" drivers, one or more "configuration"
 * objects, and a "usb_composite_driver" by gluing them together along
 * with the relevant device-wide data.
 */

static struct usb_gadget_strings **get_containers_gs(
		struct usb_gadget_string_container *uc)
{}

/**
 * function_descriptors() - get function descriptors for speed
 * @f: the function
 * @speed: the speed
 *
 * Returns the descriptors or NULL if not set.
 */
static struct usb_descriptor_header **
function_descriptors(struct usb_function *f,
		     enum usb_device_speed speed)
{}

/**
 * next_desc() - advance to the next desc_type descriptor
 * @t: currect pointer within descriptor array
 * @desc_type: descriptor type
 *
 * Return: next desc_type descriptor or NULL
 *
 * Iterate over @t until either desc_type descriptor found or
 * NULL (that indicates end of list) encountered
 */
static struct usb_descriptor_header**
next_desc(struct usb_descriptor_header **t, u8 desc_type)
{}

/*
 * for_each_desc() - iterate over desc_type descriptors in the
 * descriptors list
 * @start: pointer within descriptor array.
 * @iter_desc: desc_type descriptor to use as the loop cursor
 * @desc_type: wanted descriptr type
 */
#define for_each_desc(start, iter_desc, desc_type)

/**
 * config_ep_by_speed_and_alt() - configures the given endpoint
 * according to gadget speed.
 * @g: pointer to the gadget
 * @f: usb function
 * @_ep: the endpoint to configure
 * @alt: alternate setting number
 *
 * Return: error code, 0 on success
 *
 * This function chooses the right descriptors for a given
 * endpoint according to gadget speed and saves it in the
 * endpoint desc field. If the endpoint already has a descriptor
 * assigned to it - overwrites it with currently corresponding
 * descriptor. The endpoint maxpacket field is updated according
 * to the chosen descriptor.
 * Note: the supplied function should hold all the descriptors
 * for supported speeds
 */
int config_ep_by_speed_and_alt(struct usb_gadget *g,
				struct usb_function *f,
				struct usb_ep *_ep,
				u8 alt)
{}
EXPORT_SYMBOL_GPL();

/**
 * config_ep_by_speed() - configures the given endpoint
 * according to gadget speed.
 * @g: pointer to the gadget
 * @f: usb function
 * @_ep: the endpoint to configure
 *
 * Return: error code, 0 on success
 *
 * This function chooses the right descriptors for a given
 * endpoint according to gadget speed and saves it in the
 * endpoint desc field. If the endpoint already has a descriptor
 * assigned to it - overwrites it with currently corresponding
 * descriptor. The endpoint maxpacket field is updated according
 * to the chosen descriptor.
 * Note: the supplied function should hold all the descriptors
 * for supported speeds
 */
int config_ep_by_speed(struct usb_gadget *g,
			struct usb_function *f,
			struct usb_ep *_ep)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_add_function() - add a function to a configuration
 * @config: the configuration
 * @function: the function being added
 * Context: single threaded during gadget setup
 *
 * After initialization, each configuration must have one or more
 * functions added to it.  Adding a function involves calling its @bind()
 * method to allocate resources such as interface and string identifiers
 * and endpoints.
 *
 * This function returns the value of the function's bind(), which is
 * zero for success else a negative errno value.
 */
int usb_add_function(struct usb_configuration *config,
		struct usb_function *function)
{}
EXPORT_SYMBOL_GPL();

void usb_remove_function(struct usb_configuration *c, struct usb_function *f)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_function_deactivate - prevent function and gadget enumeration
 * @function: the function that isn't yet ready to respond
 *
 * Blocks response of the gadget driver to host enumeration by
 * preventing the data line pullup from being activated.  This is
 * normally called during @bind() processing to change from the
 * initial "ready to respond" state, or when a required resource
 * becomes available.
 *
 * For example, drivers that serve as a passthrough to a userspace
 * daemon can block enumeration unless that daemon (such as an OBEX,
 * MTP, or print server) is ready to handle host requests.
 *
 * Not all systems support software control of their USB peripheral
 * data pullups.
 *
 * Returns zero on success, else negative errno.
 */
int usb_function_deactivate(struct usb_function *function)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_function_activate - allow function and gadget enumeration
 * @function: function on which usb_function_activate() was called
 *
 * Reverses effect of usb_function_deactivate().  If no more functions
 * are delaying their activation, the gadget driver will respond to
 * host enumeration procedures.
 *
 * Returns zero on success, else negative errno.
 */
int usb_function_activate(struct usb_function *function)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_interface_id() - allocate an unused interface ID
 * @config: configuration associated with the interface
 * @function: function handling the interface
 * Context: single threaded during gadget setup
 *
 * usb_interface_id() is called from usb_function.bind() callbacks to
 * allocate new interface IDs.  The function driver will then store that
 * ID in interface, association, CDC union, and other descriptors.  It
 * will also handle any control requests targeted at that interface,
 * particularly changing its altsetting via set_alt().  There may
 * also be class-specific or vendor-specific requests to handle.
 *
 * All interface identifier should be allocated using this routine, to
 * ensure that for example different functions don't wrongly assign
 * different meanings to the same identifier.  Note that since interface
 * identifiers are configuration-specific, functions used in more than
 * one configuration (or more than once in a given configuration) need
 * multiple versions of the relevant descriptors.
 *
 * Returns the interface ID which was allocated; or -ENODEV if no
 * more interface IDs can be allocated.
 */
int usb_interface_id(struct usb_configuration *config,
		struct usb_function *function)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_func_wakeup - sends function wake notification to the host.
 * @func: function that sends the remote wakeup notification.
 *
 * Applicable to devices operating at enhanced superspeed when usb
 * functions are put in function suspend state and armed for function
 * remote wakeup. On completion, function wake notification is sent. If
 * the device is in low power state it tries to bring the device to active
 * state before sending the wake notification. Since it is a synchronous
 * call, caller must take care of not calling it in interrupt context.
 * For devices operating at lower speeds  returns negative errno.
 *
 * Returns zero on success, else negative errno.
 */
int usb_func_wakeup(struct usb_function *func)
{}
EXPORT_SYMBOL_GPL();

static u8 encode_bMaxPower(enum usb_device_speed speed,
		struct usb_configuration *c)
{}

void check_remote_wakeup_config(struct usb_gadget *g,
				struct usb_configuration *c)
{}

static int config_buf(struct usb_configuration *config,
		enum usb_device_speed speed, void *buf, u8 type)
{}

static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
{}

static int count_configs(struct usb_composite_dev *cdev, unsigned type)
{}

/**
 * bos_desc() - prepares the BOS descriptor.
 * @cdev: pointer to usb_composite device to generate the bos
 *	descriptor for
 *
 * This function generates the BOS (Binary Device Object)
 * descriptor and its device capabilities descriptors. The BOS
 * descriptor should be supported by a SuperSpeed device.
 */
static int bos_desc(struct usb_composite_dev *cdev)
{}

static void device_qual(struct usb_composite_dev *cdev)
{}

/*-------------------------------------------------------------------------*/

static void reset_config(struct usb_composite_dev *cdev)
{}

static int set_config(struct usb_composite_dev *cdev,
		const struct usb_ctrlrequest *ctrl, unsigned number)
{}

int usb_add_config_only(struct usb_composite_dev *cdev,
		struct usb_configuration *config)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_add_config() - add a configuration to a device.
 * @cdev: wraps the USB gadget
 * @config: the configuration, with bConfigurationValue assigned
 * @bind: the configuration's bind function
 * Context: single threaded during gadget setup
 *
 * One of the main tasks of a composite @bind() routine is to
 * add each of the configurations it supports, using this routine.
 *
 * This function returns the value of the configuration's @bind(), which
 * is zero for success else a negative errno value.  Binding configurations
 * assigns global resources including string IDs, and per-configuration
 * resources such as interface IDs and endpoints.
 */
int usb_add_config(struct usb_composite_dev *cdev,
		struct usb_configuration *config,
		int (*bind)(struct usb_configuration *))
{}
EXPORT_SYMBOL_GPL();

static void remove_config(struct usb_composite_dev *cdev,
			      struct usb_configuration *config)
{}

/**
 * usb_remove_config() - remove a configuration from a device.
 * @cdev: wraps the USB gadget
 * @config: the configuration
 *
 * Drivers must call usb_gadget_disconnect before calling this function
 * to disconnect the device from the host and make sure the host will not
 * try to enumerate the device while we are changing the config list.
 */
void usb_remove_config(struct usb_composite_dev *cdev,
		      struct usb_configuration *config)
{}

/*-------------------------------------------------------------------------*/

/* We support strings in multiple languages ... string descriptor zero
 * says which languages are supported.  The typical case will be that
 * only one language (probably English) is used, with i18n handled on
 * the host side.
 */

static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
{}

static int lookup_string(
	struct usb_gadget_strings	**sp,
	void				*buf,
	u16				language,
	int				id
)
{}

static int get_string(struct usb_composite_dev *cdev,
		void *buf, u16 language, int id)
{}

/**
 * usb_string_id() - allocate an unused string ID
 * @cdev: the device whose string descriptor IDs are being allocated
 * Context: single threaded during gadget setup
 *
 * @usb_string_id() is called from bind() callbacks to allocate
 * string IDs.  Drivers for functions, configurations, or gadgets will
 * then store that ID in the appropriate descriptors and string table.
 *
 * All string identifier should be allocated using this,
 * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure
 * that for example different functions don't wrongly assign different
 * meanings to the same identifier.
 */
int usb_string_id(struct usb_composite_dev *cdev)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_string_ids_tab() - allocate unused string IDs in batch
 * @cdev: the device whose string descriptor IDs are being allocated
 * @str: an array of usb_string objects to assign numbers to
 * Context: single threaded during gadget setup
 *
 * @usb_string_ids() is called from bind() callbacks to allocate
 * string IDs.  Drivers for functions, configurations, or gadgets will
 * then copy IDs from the string table to the appropriate descriptors
 * and string table for other languages.
 *
 * All string identifier should be allocated using this,
 * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for
 * example different functions don't wrongly assign different meanings
 * to the same identifier.
 */
int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
{}
EXPORT_SYMBOL_GPL();

static struct usb_gadget_string_container *copy_gadget_strings(
		struct usb_gadget_strings **sp, unsigned n_gstrings,
		unsigned n_strings)
{}

/**
 * usb_gstrings_attach() - attach gadget strings to a cdev and assign ids
 * @cdev: the device whose string descriptor IDs are being allocated
 * and attached.
 * @sp: an array of usb_gadget_strings to attach.
 * @n_strings: number of entries in each usb_strings array (sp[]->strings)
 *
 * This function will create a deep copy of usb_gadget_strings and usb_string
 * and attach it to the cdev. The actual string (usb_string.s) will not be
 * copied but only a referenced will be made. The struct usb_gadget_strings
 * array may contain multiple languages and should be NULL terminated.
 * The ->language pointer of each struct usb_gadget_strings has to contain the
 * same amount of entries.
 * For instance: sp[0] is en-US, sp[1] is es-ES. It is expected that the first
 * usb_string entry of es-ES contains the translation of the first usb_string
 * entry of en-US. Therefore both entries become the same id assign.
 */
struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev,
		struct usb_gadget_strings **sp, unsigned n_strings)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_string_ids_n() - allocate unused string IDs in batch
 * @c: the device whose string descriptor IDs are being allocated
 * @n: number of string IDs to allocate
 * Context: single threaded during gadget setup
 *
 * Returns the first requested ID.  This ID and next @n-1 IDs are now
 * valid IDs.  At least provided that @n is non-zero because if it
 * is, returns last requested ID which is now very useful information.
 *
 * @usb_string_ids_n() is called from bind() callbacks to allocate
 * string IDs.  Drivers for functions, configurations, or gadgets will
 * then store that ID in the appropriate descriptors and string table.
 *
 * All string identifier should be allocated using this,
 * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for
 * example different functions don't wrongly assign different meanings
 * to the same identifier.
 */
int usb_string_ids_n(struct usb_composite_dev *c, unsigned n)
{}
EXPORT_SYMBOL_GPL();

/*-------------------------------------------------------------------------*/

static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
{}

static int composite_ep0_queue(struct usb_composite_dev *cdev,
		struct usb_request *req, gfp_t gfp_flags)
{}

static int count_ext_compat(struct usb_configuration *c)
{}

static int fill_ext_compat(struct usb_configuration *c, u8 *buf)
{}

static int count_ext_prop(struct usb_configuration *c, int interface)
{}

static int len_ext_prop(struct usb_configuration *c, int interface)
{}

static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
{}

/*
 * The setup() callback implements all the ep0 functionality that's
 * not handled lower down, in hardware or the hardware driver(like
 * device and endpoint feature flags, and their status).  It's all
 * housekeeping for the gadget function we're implementing.  Most of
 * the work is in config and function specific setup.
 */
int
composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
{}

static void __composite_disconnect(struct usb_gadget *gadget)
{}

void composite_disconnect(struct usb_gadget *gadget)
{}

void composite_reset(struct usb_gadget *gadget)
{}

/*-------------------------------------------------------------------------*/

static ssize_t suspended_show(struct device *dev, struct device_attribute *attr,
			      char *buf)
{}
static DEVICE_ATTR_RO(suspended);

static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
{}

static void composite_unbind(struct usb_gadget *gadget)
{}

static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
		const struct usb_device_descriptor *old)
{}

int composite_dev_prepare(struct usb_composite_driver *composite,
		struct usb_composite_dev *cdev)
{}

int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
				  struct usb_ep *ep0)
{}

void composite_dev_cleanup(struct usb_composite_dev *cdev)
{}

static int composite_bind(struct usb_gadget *gadget,
		struct usb_gadget_driver *gdriver)
{}

/*-------------------------------------------------------------------------*/

void composite_suspend(struct usb_gadget *gadget)
{}

void composite_resume(struct usb_gadget *gadget)
{}

/*-------------------------------------------------------------------------*/

static const struct usb_gadget_driver composite_driver_template =;

/**
 * usb_composite_probe() - register a composite driver
 * @driver: the driver to register
 *
 * Context: single threaded during gadget setup
 *
 * This function is used to register drivers using the composite driver
 * framework.  The return value is zero, or a negative errno value.
 * Those values normally come from the driver's @bind method, which does
 * all the work of setting up the driver to match the hardware.
 *
 * On successful return, the gadget is ready to respond to requests from
 * the host, unless one of its components invokes usb_gadget_disconnect()
 * while it was binding.  That would usually be done in order to wait for
 * some userspace participation.
 */
int usb_composite_probe(struct usb_composite_driver *driver)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_composite_unregister() - unregister a composite driver
 * @driver: the driver to unregister
 *
 * This function is used to unregister drivers using the composite
 * driver framework.
 */
void usb_composite_unregister(struct usb_composite_driver *driver)
{}
EXPORT_SYMBOL_GPL();

/**
 * usb_composite_setup_continue() - Continue with the control transfer
 * @cdev: the composite device who's control transfer was kept waiting
 *
 * This function must be called by the USB function driver to continue
 * with the control transfer's data/status stage in case it had requested to
 * delay the data/status stages. A USB function's setup handler (e.g. set_alt())
 * can request the composite framework to delay the setup request's data/status
 * stages by returning USB_GADGET_DELAYED_STATUS.
 */
void usb_composite_setup_continue(struct usb_composite_dev *cdev)
{}
EXPORT_SYMBOL_GPL();

static char *composite_default_mfr(struct usb_gadget *gadget)
{}

void usb_composite_overwrite_options(struct usb_composite_dev *cdev,
		struct usb_composite_overwrite *covr)
{}
EXPORT_SYMBOL_GPL();

MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_AUTHOR();