usb: gadget: OS Feature Descriptors support

This is a proting patch from linux kernel: 37a3a533429e
("usb: gadget: OS Feature Descriptors support"), the original commit
log see below:

There is a custom (non-USB IF) extension to the USB standard:

http://msdn.microsoft.com/library/windows/hardware/gg463182

They grant permission to use the specification - there is
"Microsoft OS Descriptor Specification License Agreement"
under the link mentioned above, and its Section 2 "Grant
of License", letter (b) reads:

"Patent license. Microsoft hereby grants to You a nonexclusive,
royalty-free, nontransferable, worldwide license under Microsoft鈥檚
patents embodied solely within the Specification and that are owned
or licensable by Microsoft to make, use, import, offer to sell,
sell and distribute directly or indirectly to Your Licensees Your
Implementation. You may sublicense this patent license to Your
Licensees under the same terms and conditions."

The said extension is maintained by Microsoft for Microsoft.

Yet it is fairly common for various devices to use it, and a
popular proprietary operating system expects devices to provide
"OS descriptors", so Linux-based USB gadgets whishing to be able
to talk to a variety of operating systems should be able to provide
the "OS descriptors".

This patch adds optional support for gadgets whishing to expose
the so called "OS Feature Descriptors", that is "Extended Compatibility ID"
and "Extended Properties".

Hosts which do request "OS descriptors" from gadgets do so during
the enumeration phase and before the configuration is set with
SET_CONFIGURATION. What is more, those hosts never ask for configurations
at indices other than 0. Therefore, gadgets whishing to provide
"OS descriptors" must designate one configuration to be used with
this kind of hosts - this is what os_desc_config is added for in
struct usb_composite_dev. There is an additional advantage to it:
if a gadget provides "OS descriptors" and designates one configuration
to be used with such non-USB-compliant hosts it can invoke
"usb_add_config" in any order because the designated configuration
will be reported to be at index 0 anyway.

This patch also adds handling vendor-specific requests addressed
at device or interface and related to handling "OS descriptors"."

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
Li Jun 2021-01-25 21:43:49 +08:00 committed by Marek Vasut
parent 16fd832e0e
commit a764c94128
3 changed files with 431 additions and 1 deletions

View file

@ -37,6 +37,53 @@
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
*/
struct usb_os_desc_ext_prop {
struct list_head entry;
u8 type;
int name_len;
char *name;
int data_len;
char *data;
};
/**
* 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
*/
struct usb_os_desc {
char *ext_compat_id;
struct list_head ext_prop;
int ext_prop_len;
int ext_prop_count;
};
/**
* 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.
@ -50,6 +97,10 @@ struct usb_configuration;
* the function will not be available at high speed.
* @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.
@ -98,6 +149,9 @@ struct usb_function {
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.
@ -292,10 +346,12 @@ extern void usb_composite_unregister(struct usb_composite_driver *);
* @gadget: read-only, abstracts the gadget's usb peripheral controller
* @req: used for control responses; buffer is pre-allocated
* @bufsiz: size of buffer pre-allocated in @req
* @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
* @os_desc_config: the configuration to be used with OS descriptors
*
* One of these devices is allocated and initialized before the
* associated device driver's bind() is called.
@ -332,6 +388,7 @@ struct usb_composite_dev {
/* 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;
/* private: */