// 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(…) …;