// SPDX-License-Identifier: GPL-2.0+
/*
* composite . h - - framework for usb gadgets which are composite devices
*
* Copyright ( C ) 2006 - 2008 David Brownell
*/
#ifndef __LINUX_USB_COMPOSITE_H
#define __LINUX_USB_COMPOSITE_H
/*
* This framework is an optional layer on top of the USB Gadget interface ,
* making it easier to build ( a ) Composite devices , supporting multiple
* functions within any single configuration , and ( b ) Multi - configuration
* devices , also supporting multiple functions but without necessarily
* having more than one function per configuration .
*
* Example : a device with a single configuration supporting both network
* link and mass storage functions is a composite device . Those functions
* might alternatively be packaged in individual configurations , but in
* the composite model the host can use both functions at the same time .
*/
#include <linux/bcd.h>
#include <linux/version.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/webusb.h>
#include <linux/log2.h>
#include <linux/configfs.h>
/*
* USB function drivers should return USB_GADGET_DELAYED_STATUS if they
* wish to delay the data / status stages of the control transfer till they
* are ready . The control transfer will then be kept from completing till
* all the function drivers that requested for USB_GADGET_DELAYED_STAUS
* invoke usb_composite_setup_continue ( ) .
*
* NOTE : USB_GADGET_DELAYED_STATUS must not be used in UDC drivers : they
* must delay completing the status stage for 0 - length control transfers
* regardless of the whether USB_GADGET_DELAYED_STATUS is returned from
* the gadget driver ' s setup ( ) callback .
* Currently , a number of UDC drivers rely on USB_GADGET_DELAYED_STATUS ,
* which is a bug . These drivers must be fixed and USB_GADGET_DELAYED_STATUS
* must be contained within the composite framework .
*/
#define USB_GADGET_DELAYED_STATUS 0 x7fff /* Impossibly large value */
/* big enough to hold our biggest descriptor */
#define USB_COMP_EP0_BUFSIZ 4096
/* OS feature descriptor length <= 4kB */
#define USB_COMP_EP0_OS_DESC_BUFSIZ 4096
#define USB_MS_TO_HS_INTERVAL(x) (ilog2((x * 1000 / 125 )) + 1 )
struct usb_configuration;
/**
* struct usb_os_desc_ext_prop - describes one " Extended Property "
* @ entry : used to keep a list of extended properties
* @ type : Extended Property type
* @ name_len : Extended Property unicode name length , including terminating ' \ 0 '
* @ name : Extended Property name
* @ data_len : Length of Extended Property blob ( for unicode store double len )
* @ data : Extended Property blob
* @ item : Represents this Extended Property in configfs
*/
struct usb_os_desc_ext_prop {
struct list_head entry;
u8 type;
int name_len;
char *name;
int data_len;
char *data;
struct config_item item;
};
/**
* struct usb_os_desc - describes OS descriptors associated with one interface
* @ ext_compat_id : 16 bytes of " Compatible ID " and " Subcompatible ID "
* @ ext_prop : Extended Properties list
* @ ext_prop_len : Total length of Extended Properties blobs
* @ ext_prop_count : Number of Extended Properties
* @ opts_mutex : Optional mutex protecting config data of a usb_function_instance
* @ group : Represents OS descriptors associated with an interface in configfs
* @ owner : Module associated with this OS descriptor
*/
struct usb_os_desc {
char *ext_compat_id;
struct list_head ext_prop;
int ext_prop_len;
int ext_prop_count;
struct mutex *opts_mutex;
struct config_group group;
struct module *owner;
};
/**
* struct usb_os_desc_table - describes OS descriptors associated with one
* interface of a usb_function
* @ if_id : Interface id
* @ os_desc : " Extended Compatibility ID " and " Extended Properties " of the
* interface
*
* Each interface can have at most one " Extended Compatibility ID " and a
* number of " Extended Properties " .
*/
struct usb_os_desc_table {
int if_id;
struct usb_os_desc *os_desc;
};
/**
* struct usb_function - describes one function of a configuration
* @ name : For diagnostics , identifies the function .
* @ strings : tables of strings , keyed by identifiers assigned during bind ( )
* and by language IDs provided in control requests
* @ fs_descriptors : Table of full ( or low ) speed descriptors , using interface and
* string identifiers assigned during @ bind ( ) . If this pointer is null ,
* the function will not be available at full speed ( or at low speed ) .
* @ hs_descriptors : Table of high speed descriptors , using interface and
* string identifiers assigned during @ bind ( ) . If this pointer is null ,
* the function will not be available at high speed .
* @ ss_descriptors : Table of super speed descriptors , using interface and
* string identifiers assigned during @ bind ( ) . If this
* pointer is null after initiation , the function will not
* be available at super speed .
* @ ssp_descriptors : Table of super speed plus descriptors , using
* interface and string identifiers assigned during @ bind ( ) . If
* this pointer is null after initiation , the function will not
* be available at super speed plus .
* @ config : assigned when @ usb_add_function ( ) is called ; this is the
* configuration with which this function is associated .
* @ os_desc_table : Table of ( interface id , os descriptors ) pairs . The function
* can expose more than one interface . If an interface is a member of
* an IAD , only the first interface of IAD has its entry in the table .
* @ os_desc_n : Number of entries in os_desc_table
* @ bind : Before the gadget can register , all of its functions bind ( ) to the
* available resources including string and interface identifiers used
* in interface or class descriptors ; endpoints ; I / O buffers ; and so on .
* @ unbind : Reverses @ bind ; called as a side effect of unregistering the
* driver which added this function .
* @ free_func : free the struct usb_function .
* @ mod : ( internal ) points to the module that created this structure .
* @ set_alt : ( REQUIRED ) Reconfigures altsettings ; function drivers may
* initialize usb_ep . driver data at this time ( when it is used ) .
* Note that setting an interface to its current altsetting resets
* interface state , and that all interfaces have a disabled state .
* @ get_alt : Returns the active altsetting . If this is not provided ,
* then only altsetting zero is supported .
* @ disable : ( REQUIRED ) Indicates the function should be disabled . Reasons
* include host resetting or reconfiguring the gadget , and disconnection .
* @ setup : Used for interface - specific control requests .
* @ req_match : Tests if a given class request can be handled by this function .
* @ suspend : Notifies functions when the host stops sending USB traffic .
* @ resume : Notifies functions when the host restarts USB traffic .
* @ get_status : Returns function status as a reply to
* GetStatus ( ) request when the recipient is Interface .
* @ func_suspend : callback to be called when
* SetFeature ( FUNCTION_SUSPEND ) is reseived
* @ func_suspended : Indicates whether the function is in function suspend state .
* @ func_wakeup_armed : Indicates whether the function is armed by the host for
* wakeup signaling .
*
* A single USB function uses one or more interfaces , and should in most
* cases support operation at both full and high speeds . Each function is
* associated by @ usb_add_function ( ) with a one configuration ; that function
* causes @ bind ( ) to be called so resources can be allocated as part of
* setting up a gadget driver . Those resources include endpoints , which
* should be allocated using @ usb_ep_autoconfig ( ) .
*
* To support dual speed operation , a function driver provides descriptors
* for both high and full speed operation . Except in rare cases that don ' t
* involve bulk endpoints , each speed needs different endpoint descriptors .
*
* Function drivers choose their own strategies for managing instance data .
* The simplest strategy just declares it " static ' , which means the function
* can only be activated once . If the function needs to be exposed in more
* than one configuration at a given speed , it needs to support multiple
* usb_function structures ( one for each configuration ) .
*
* A more complex strategy might encapsulate a @ usb_function structure inside
* a driver - specific instance structure to allows multiple activations . An
* example of multiple activations might be a CDC ACM function that supports
* two or more distinct instances within the same configuration , providing
* several independent logical data links to a USB host .
*/
struct usb_function {
const char *name;
struct usb_gadget_strings **strings;
struct usb_descriptor_header **fs_descriptors;
struct usb_descriptor_header **hs_descriptors;
struct usb_descriptor_header **ss_descriptors;
struct usb_descriptor_header **ssp_descriptors;
struct usb_configuration *config;
struct usb_os_desc_table *os_desc_table;
unsigned os_desc_n;
/* REVISIT: bind() functions can be marked __init, which
* makes trouble for section mismatch analysis . See if
* we can ' t restructure things to avoid mismatching .
* Related : unbind ( ) may kfree ( ) but bind ( ) won ' t . . .
*/
/* configuration management: bind/unbind */
int (*bind)(struct usb_configuration *,
struct usb_function *);
void (*unbind)(struct usb_configuration *,
struct usb_function *);
void (*free_func)(struct usb_function *f);
struct module *mod;
/* runtime state management */
int (*set_alt)(struct usb_function *,
unsigned interface, unsigned alt);
int (*get_alt)(struct usb_function *,
unsigned interface);
void (*disable)(struct usb_function *);
int (*setup)(struct usb_function *,
const struct usb_ctrlrequest *);
bool (*req_match)(struct usb_function *,
const struct usb_ctrlrequest *,
bool config0);
void (*suspend)(struct usb_function *);
void (*resume)(struct usb_function *);
/* USB 3.0 additions */
int (*get_status)(struct usb_function *);
int (*func_suspend)(struct usb_function *,
u8 suspend_opt);
bool func_suspended;
bool func_wakeup_armed;
/* private: */
/* internals */
struct list_head list;
DECLARE_BITMAP(endpoints, 32 );
struct usb_function_instance *fi;
unsigned int bind_deactivated:1 ;
};
int usb_add_function(struct usb_configuration *, struct usb_function *);
int usb_function_deactivate(struct usb_function *);
int usb_function_activate(struct usb_function *);
int usb_interface_id(struct usb_configuration *, struct usb_function *);
int config_ep_by_speed_and_alt(struct usb_gadget *g, struct usb_function *f,
struct usb_ep *_ep, u8 alt);
int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
struct usb_ep *_ep);
int usb_func_wakeup(struct usb_function *func);
#define MAX_CONFIG_INTERFACES 32
/**
* struct usb_configuration - represents one gadget configuration
* @ label : For diagnostics , describes the configuration .
* @ strings : Tables of strings , keyed by identifiers assigned during @ bind ( )
* and by language IDs provided in control requests .
* @ descriptors : Table of descriptors preceding all function descriptors .
* Examples include OTG and vendor - specific descriptors .
* @ unbind : Reverses @ bind ; called as a side effect of unregistering the
* driver which added this configuration .
* @ setup : Used to delegate control requests that aren ' t handled by standard
* device infrastructure or directed at a specific interface .
* @ bConfigurationValue : Copied into configuration descriptor .
* @ iConfiguration : Copied into configuration descriptor .
* @ bmAttributes : Copied into configuration descriptor .
* @ MaxPower : Power consumption in mA . Used to compute bMaxPower in the
* configuration descriptor after considering the bus speed .
* @ cdev : assigned by @ usb_add_config ( ) before calling @ bind ( ) ; this is
* the device associated with this configuration .
*
* Configurations are building blocks for gadget drivers structured around
* function drivers . Simple USB gadgets require only one function and one
* configuration , and handle dual - speed hardware by always providing the same
* functionality . Slightly more complex gadgets may have more than one
* single - function configuration at a given speed ; or have configurations
* that only work at one speed .
*
* Composite devices are , by definition , ones with configurations which
* include more than one function .
*
* The lifecycle of a usb_configuration includes allocation , initialization
* of the fields described above , and calling @ usb_add_config ( ) to set up
* internal data and bind it to a specific device . The configuration ' s
* @ bind ( ) method is then used to initialize all the functions and then
* call @ usb_add_function ( ) for them .
*
* Those functions would normally be independent of each other , but that ' s
* not mandatory . CDC WMC devices are an example where functions often
* depend on other functions , with some functions subsidiary to others .
* Such interdependency may be managed in any way , so long as all of the
* descriptors complete by the time the composite driver returns from
* its bind ( ) routine .
*/
struct usb_configuration {
const char *label;
struct usb_gadget_strings **strings;
const struct usb_descriptor_header **descriptors;
/* REVISIT: bind() functions can be marked __init, which
* makes trouble for section mismatch analysis . See if
* we can ' t restructure things to avoid mismatching . . .
*/
/* configuration management: unbind/setup */
void (*unbind)(struct usb_configuration *);
int (*setup)(struct usb_configuration *,
const struct usb_ctrlrequest *);
/* fields in the config descriptor */
u8 bConfigurationValue;
u8 iConfiguration;
u8 bmAttributes;
u16 MaxPower;
struct usb_composite_dev *cdev;
/* private: */
/* internals */
struct list_head list;
struct list_head functions;
u8 next_interface_id;
unsigned superspeed:1 ;
unsigned highspeed:1 ;
unsigned fullspeed:1 ;
unsigned superspeed_plus:1 ;
struct usb_function *interface[MAX_CONFIG_INTERFACES];
};
int usb_add_config(struct usb_composite_dev *,
struct usb_configuration *,
int (*)(struct usb_configuration *));
/* predefined index for usb_composite_driver */
enum {
USB_GADGET_MANUFACTURER_IDX = 0 ,
USB_GADGET_PRODUCT_IDX,
USB_GADGET_SERIAL_IDX,
USB_GADGET_FIRST_AVAIL_IDX,
};
/**
* struct usb_composite_driver - groups configurations into a gadget
* @ name : For diagnostics , identifies the driver .
* @ dev : Template descriptor for the device , including default device
* identifiers .
* @ strings : tables of strings , keyed by identifiers assigned during @ bind
* and language IDs provided in control requests . Note : The first entries
* are predefined . The first entry that may be used is
* USB_GADGET_FIRST_AVAIL_IDX
* @ max_speed : Highest speed the driver supports .
* @ needs_serial : set to 1 if the gadget needs userspace to provide
* a serial number . If one is not provided , warning will be printed .
* @ bind : ( REQUIRED ) Used to allocate resources that are shared across the
* whole device , such as string IDs , and add its configurations using
* @ usb_add_config ( ) . This may fail by returning a negative errno
* value ; it should return zero on successful initialization .
* @ unbind : Reverses @ bind ; called as a side effect of unregistering
* this driver .
* @ disconnect : optional driver disconnect method
* @ suspend : Notifies when the host stops sending USB traffic ,
* after function notifications
* @ resume : Notifies configuration when the host restarts USB traffic ,
* before function notifications
* @ gadget_driver : Gadget driver controlling this driver
*
* Devices default to reporting self powered operation . Devices which rely
* on bus powered operation should report this in their @ bind method .
*
* Before returning from @ bind , various fields in the template descriptor
* may be overridden . These include the idVendor / idProduct / bcdDevice values
* normally to bind the appropriate host side driver , and the three strings
* ( iManufacturer , iProduct , iSerialNumber ) normally used to provide user
* meaningful device identifiers . ( The strings will not be defined unless
* they are defined in @ dev and @ strings . ) The correct ep0 maxpacket size
* is also reported , as defined by the underlying controller driver .
*/
struct usb_composite_driver {
const char *name;
const struct usb_device_descriptor *dev;
struct usb_gadget_strings **strings;
enum usb_device_speed max_speed;
unsigned needs_serial:1 ;
int (*bind)(struct usb_composite_dev *cdev);
int (*unbind)(struct usb_composite_dev *);
void (*disconnect)(struct usb_composite_dev *);
/* global suspend hooks */
void (*suspend)(struct usb_composite_dev *);
void (*resume)(struct usb_composite_dev *);
struct usb_gadget_driver gadget_driver;
};
extern int usb_composite_probe(struct usb_composite_driver *driver);
extern void usb_composite_unregister(struct usb_composite_driver *driver);
/**
* module_usb_composite_driver ( ) - Helper macro for registering a USB gadget
* composite driver
* @ _ _ usb_composite_driver : usb_composite_driver struct
*
* Helper macro for USB gadget composite drivers which do not do anything
* special in module init / exit . This eliminates a lot of boilerplate . Each
* module may only use this macro once , and calling it replaces module_init ( )
* and module_exit ( )
*/
#define module_usb_composite_driver(__usb_composite_driver) \
module_driver(__usb_composite_driver, usb_composite_probe, \
usb_composite_unregister)
extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
extern int composite_dev_prepare(struct usb_composite_driver *composite,
struct usb_composite_dev *cdev);
extern int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
struct usb_ep *ep0);
void composite_dev_cleanup(struct usb_composite_dev *cdev);
void check_remote_wakeup_config(struct usb_gadget *g,
struct usb_configuration *c);
static inline struct usb_composite_driver *to_cdriver(
struct usb_gadget_driver *gdrv)
{
return container_of(gdrv, struct usb_composite_driver, gadget_driver);
}
#define OS_STRING_QW_SIGN_LEN 14
#define OS_STRING_IDX 0 xEE
/**
* struct usb_composite_dev - represents one composite usb gadget
* @ gadget : read - only , abstracts the gadget ' s usb peripheral controller
* @ req : used for control responses ; buffer is pre - allocated
* @ os_desc_req : used for OS descriptors responses ; buffer is pre - allocated
* @ config : the currently active configuration
* @ qw_sign : qwSignature part of the OS string
* @ b_vendor_code : bMS_VendorCode part of the OS string
* @ use_os_string : false by default , interested gadgets set it
* @ bcd_webusb_version : 0 x0100 by default , WebUSB specification version
* @ b_webusb_vendor_code : 0 x0 by default , vendor code for WebUSB
* @ landing_page : empty by default , landing page to announce in WebUSB
* @ use_webusb : false by default , interested gadgets set it
* @ os_desc_config : the configuration to be used with OS descriptors
* @ setup_pending : true when setup request is queued but not completed
* @ os_desc_pending : true when os_desc request is queued but not completed
*
* One of these devices is allocated and initialized before the
* associated device driver ' s bind ( ) is called .
*/
struct usb_composite_dev {
struct usb_gadget *gadget;
struct usb_request *req;
struct usb_request *os_desc_req;
struct usb_configuration *config;
/* OS String is a custom (yet popular) extension to the USB standard. */
u8 qw_sign[OS_STRING_QW_SIGN_LEN];
u8 b_vendor_code;
struct usb_configuration *os_desc_config;
unsigned int use_os_string:1 ;
/* WebUSB */
u16 bcd_webusb_version;
u8 b_webusb_vendor_code;
char landing_page[WEBUSB_URL_RAW_MAX_LENGTH];
unsigned int use_webusb:1 ;
/* private: */
/* internals */
unsigned int suspended:1 ;
struct usb_device_descriptor desc;
struct list_head configs;
struct list_head gstrings;
struct usb_composite_driver *driver;
u8 next_string_id;
char *def_manufacturer;
struct usb_string *usb_strings;
/* the gadget driver won't enable the data pullup
* while the deactivation count is nonzero .
*/
unsigned deactivations;
/* the composite driver won't complete the control transfer's
* data / status stages till delayed_status is zero .
*/
int delayed_status;
/* protects deactivations and delayed_status counts*/
spinlock_t lock;
/* public: */
unsigned int setup_pending:1 ;
unsigned int os_desc_pending:1 ;
};
extern int usb_string_id(struct usb_composite_dev *c);
extern int usb_string_ids_tab(struct usb_composite_dev *c,
struct usb_string *str);
extern struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev,
struct usb_gadget_strings **sp, unsigned n_strings);
extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
extern void composite_disconnect(struct usb_gadget *gadget);
extern void composite_reset(struct usb_gadget *gadget);
extern int composite_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl);
extern void composite_suspend(struct usb_gadget *gadget);
extern void composite_resume(struct usb_gadget *gadget);
/*
* Some systems will need runtime overrides for the product identifiers
* published in the device descriptor , either numbers or strings or both .
* String parameters are in UTF - 8 ( superset of ASCII ' s 7 bit characters ) .
*/
struct usb_composite_overwrite {
u16 idVendor;
u16 idProduct;
u16 bcdDevice;
char *serial_number;
char *manufacturer;
char *product;
};
#define USB_GADGET_COMPOSITE_OPTIONS() \
static struct usb_composite_overwrite coverwrite; \
\
module_param_named(idVendor, coverwrite.idVendor, ushort, S_IRUGO); \
MODULE_PARM_DESC(idVendor, "USB Vendor ID" ); \
\
module_param_named(idProduct, coverwrite.idProduct, ushort, S_IRUGO); \
MODULE_PARM_DESC(idProduct, "USB Product ID" ); \
\
module_param_named(bcdDevice, coverwrite.bcdDevice, ushort, S_IRUGO); \
MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)" ); \
\
module_param_named(iSerialNumber, coverwrite.serial_number, charp, \
S_IRUGO); \
MODULE_PARM_DESC(iSerialNumber, "SerialNumber string" ); \
\
module_param_named(iManufacturer, coverwrite.manufacturer, charp, \
S_IRUGO); \
MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string" ); \
\
module_param_named(iProduct, coverwrite.product, charp, S_IRUGO); \
MODULE_PARM_DESC(iProduct, "USB Product string" )
void usb_composite_overwrite_options(struct usb_composite_dev *cdev,
struct usb_composite_overwrite *covr);
static inline u16 get_default_bcdDevice(void )
{
u16 bcdDevice;
bcdDevice = bin2bcd(LINUX_VERSION_MAJOR) << 8 ;
bcdDevice |= bin2bcd(LINUX_VERSION_PATCHLEVEL);
return bcdDevice;
}
struct usb_function_driver {
const char *name;
struct module *mod;
struct list_head list;
struct usb_function_instance *(*alloc_inst)(void );
struct usb_function *(*alloc_func)(struct usb_function_instance *inst);
};
struct usb_function_instance {
struct config_group group;
struct list_head cfs_list;
struct usb_function_driver *fd;
int (*set_inst_name)(struct usb_function_instance *inst,
const char *name);
void (*free_func_inst)(struct usb_function_instance *inst);
};
void usb_function_unregister(struct usb_function_driver *f);
int usb_function_register(struct usb_function_driver *newf);
void usb_put_function_instance(struct usb_function_instance *fi);
void usb_put_function(struct usb_function *f);
struct usb_function_instance *usb_get_function_instance(const char *name);
struct usb_function *usb_get_function(struct usb_function_instance *fi);
struct usb_configuration *usb_get_config(struct usb_composite_dev *cdev,
int val);
int usb_add_config_only(struct usb_composite_dev *cdev,
struct usb_configuration *config);
void usb_remove_function(struct usb_configuration *c, struct usb_function *f);
#define DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \
static struct usb_function_driver _name ## usb_func = { \
.name = __stringify(_name), \
.mod = THIS_MODULE, \
.alloc_inst = _inst_alloc, \
.alloc_func = _func_alloc, \
}; \
MODULE_ALIAS("usbfunc:" __stringify(_name));
#define DECLARE_USB_FUNCTION_INIT(_name, _inst_alloc, _func_alloc) \
DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \
static int __init _name ## mod_init(void ) \
{ \
return usb_function_register(&_name ## usb_func); \
} \
static void __exit _name ## mod_exit(void ) \
{ \
usb_function_unregister(&_name ## usb_func); \
} \
module_init(_name ## mod_init); \
module_exit(_name ## mod_exit)
/* messaging utils */
#define DBG(d, fmt, args...) \
dev_dbg(&(d)->gadget->dev , fmt , ## args)
#define VDBG(d, fmt, args...) \
dev_vdbg(&(d)->gadget->dev , fmt , ## args)
#define ERROR(d, fmt, args...) \
dev_err(&(d)->gadget->dev , fmt , ## args)
#define WARNING(d, fmt, args...) \
dev_warn(&(d)->gadget->dev , fmt , ## args)
#define INFO(d, fmt, args...) \
dev_info(&(d)->gadget->dev , fmt , ## args)
#endif /* __LINUX_USB_COMPOSITE_H */
Messung V0.5 in Prozent C=95 H=100 G=97
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland