Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * usb/gadget/config.c -- simplify building config descriptors
0004  *
0005  * Copyright (C) 2003 David Brownell
0006  */
0007 
0008 #include <linux/errno.h>
0009 #include <linux/slab.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/list.h>
0013 #include <linux/string.h>
0014 #include <linux/device.h>
0015 
0016 #include <linux/usb/ch9.h>
0017 #include <linux/usb/gadget.h>
0018 #include <linux/usb/composite.h>
0019 #include <linux/usb/otg.h>
0020 
0021 /**
0022  * usb_descriptor_fillbuf - fill buffer with descriptors
0023  * @buf: Buffer to be filled
0024  * @buflen: Size of buf
0025  * @src: Array of descriptor pointers, terminated by null pointer.
0026  *
0027  * Copies descriptors into the buffer, returning the length or a
0028  * negative error code if they can't all be copied.  Useful when
0029  * assembling descriptors for an associated set of interfaces used
0030  * as part of configuring a composite device; or in other cases where
0031  * sets of descriptors need to be marshaled.
0032  */
0033 int
0034 usb_descriptor_fillbuf(void *buf, unsigned buflen,
0035         const struct usb_descriptor_header **src)
0036 {
0037     u8  *dest = buf;
0038 
0039     if (!src)
0040         return -EINVAL;
0041 
0042     /* fill buffer from src[] until null descriptor ptr */
0043     for (; NULL != *src; src++) {
0044         unsigned        len = (*src)->bLength;
0045 
0046         if (len > buflen)
0047             return -EINVAL;
0048         memcpy(dest, *src, len);
0049         buflen -= len;
0050         dest += len;
0051     }
0052     return dest - (u8 *)buf;
0053 }
0054 EXPORT_SYMBOL_GPL(usb_descriptor_fillbuf);
0055 
0056 /**
0057  * usb_gadget_config_buf - builts a complete configuration descriptor
0058  * @config: Header for the descriptor, including characteristics such
0059  *  as power requirements and number of interfaces.
0060  * @desc: Null-terminated vector of pointers to the descriptors (interface,
0061  *  endpoint, etc) defining all functions in this device configuration.
0062  * @buf: Buffer for the resulting configuration descriptor.
0063  * @length: Length of buffer.  If this is not big enough to hold the
0064  *  entire configuration descriptor, an error code will be returned.
0065  *
0066  * This copies descriptors into the response buffer, building a descriptor
0067  * for that configuration.  It returns the buffer length or a negative
0068  * status code.  The config.wTotalLength field is set to match the length
0069  * of the result, but other descriptor fields (including power usage and
0070  * interface count) must be set by the caller.
0071  *
0072  * Gadget drivers could use this when constructing a config descriptor
0073  * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
0074  * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
0075  */
0076 int usb_gadget_config_buf(
0077     const struct usb_config_descriptor  *config,
0078     void                    *buf,
0079     unsigned                length,
0080     const struct usb_descriptor_header  **desc
0081 )
0082 {
0083     struct usb_config_descriptor        *cp = buf;
0084     int                 len;
0085 
0086     /* config descriptor first */
0087     if (length < USB_DT_CONFIG_SIZE || !desc)
0088         return -EINVAL;
0089     *cp = *config;
0090 
0091     /* then interface/endpoint/class/vendor/... */
0092     len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8 *)buf,
0093             length - USB_DT_CONFIG_SIZE, desc);
0094     if (len < 0)
0095         return len;
0096     len += USB_DT_CONFIG_SIZE;
0097     if (len > 0xffff)
0098         return -EINVAL;
0099 
0100     /* patch up the config descriptor */
0101     cp->bLength = USB_DT_CONFIG_SIZE;
0102     cp->bDescriptorType = USB_DT_CONFIG;
0103     cp->wTotalLength = cpu_to_le16(len);
0104     cp->bmAttributes |= USB_CONFIG_ATT_ONE;
0105     return len;
0106 }
0107 EXPORT_SYMBOL_GPL(usb_gadget_config_buf);
0108 
0109 /**
0110  * usb_copy_descriptors - copy a vector of USB descriptors
0111  * @src: null-terminated vector to copy
0112  * Context: initialization code, which may sleep
0113  *
0114  * This makes a copy of a vector of USB descriptors.  Its primary use
0115  * is to support usb_function objects which can have multiple copies,
0116  * each needing different descriptors.  Functions may have static
0117  * tables of descriptors, which are used as templates and customized
0118  * with identifiers (for interfaces, strings, endpoints, and more)
0119  * as needed by a given function instance.
0120  */
0121 struct usb_descriptor_header **
0122 usb_copy_descriptors(struct usb_descriptor_header **src)
0123 {
0124     struct usb_descriptor_header **tmp;
0125     unsigned bytes;
0126     unsigned n_desc;
0127     void *mem;
0128     struct usb_descriptor_header **ret;
0129 
0130     /* count descriptors and their sizes; then add vector size */
0131     for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++)
0132         bytes += (*tmp)->bLength;
0133     bytes += (n_desc + 1) * sizeof(*tmp);
0134 
0135     mem = kmalloc(bytes, GFP_KERNEL);
0136     if (!mem)
0137         return NULL;
0138 
0139     /* fill in pointers starting at "tmp",
0140      * to descriptors copied starting at "mem";
0141      * and return "ret"
0142      */
0143     tmp = mem;
0144     ret = mem;
0145     mem += (n_desc + 1) * sizeof(*tmp);
0146     while (*src) {
0147         memcpy(mem, *src, (*src)->bLength);
0148         *tmp = mem;
0149         tmp++;
0150         mem += (*src)->bLength;
0151         src++;
0152     }
0153     *tmp = NULL;
0154 
0155     return ret;
0156 }
0157 EXPORT_SYMBOL_GPL(usb_copy_descriptors);
0158 
0159 int usb_assign_descriptors(struct usb_function *f,
0160         struct usb_descriptor_header **fs,
0161         struct usb_descriptor_header **hs,
0162         struct usb_descriptor_header **ss,
0163         struct usb_descriptor_header **ssp)
0164 {
0165     struct usb_gadget *g = f->config->cdev->gadget;
0166 
0167     /* super-speed-plus descriptor falls back to super-speed one,
0168      * if such a descriptor was provided, thus avoiding a NULL
0169      * pointer dereference if a 5gbps capable gadget is used with
0170      * a 10gbps capable config (device port + cable + host port)
0171      */
0172     if (!ssp)
0173         ssp = ss;
0174 
0175     if (fs) {
0176         f->fs_descriptors = usb_copy_descriptors(fs);
0177         if (!f->fs_descriptors)
0178             goto err;
0179     }
0180     if (hs && gadget_is_dualspeed(g)) {
0181         f->hs_descriptors = usb_copy_descriptors(hs);
0182         if (!f->hs_descriptors)
0183             goto err;
0184     }
0185     if (ss && gadget_is_superspeed(g)) {
0186         f->ss_descriptors = usb_copy_descriptors(ss);
0187         if (!f->ss_descriptors)
0188             goto err;
0189     }
0190     if (ssp && gadget_is_superspeed_plus(g)) {
0191         f->ssp_descriptors = usb_copy_descriptors(ssp);
0192         if (!f->ssp_descriptors)
0193             goto err;
0194     }
0195     return 0;
0196 err:
0197     usb_free_all_descriptors(f);
0198     return -ENOMEM;
0199 }
0200 EXPORT_SYMBOL_GPL(usb_assign_descriptors);
0201 
0202 void usb_free_all_descriptors(struct usb_function *f)
0203 {
0204     usb_free_descriptors(f->fs_descriptors);
0205     f->fs_descriptors = NULL;
0206     usb_free_descriptors(f->hs_descriptors);
0207     f->hs_descriptors = NULL;
0208     usb_free_descriptors(f->ss_descriptors);
0209     f->ss_descriptors = NULL;
0210     usb_free_descriptors(f->ssp_descriptors);
0211     f->ssp_descriptors = NULL;
0212 }
0213 EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
0214 
0215 struct usb_descriptor_header *usb_otg_descriptor_alloc(
0216                 struct usb_gadget *gadget)
0217 {
0218     struct usb_descriptor_header *otg_desc;
0219     unsigned length = 0;
0220 
0221     if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200))
0222         length = sizeof(struct usb_otg20_descriptor);
0223     else
0224         length = sizeof(struct usb_otg_descriptor);
0225 
0226     otg_desc = kzalloc(length, GFP_KERNEL);
0227     return otg_desc;
0228 }
0229 EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc);
0230 
0231 int usb_otg_descriptor_init(struct usb_gadget *gadget,
0232         struct usb_descriptor_header *otg_desc)
0233 {
0234     struct usb_otg_descriptor *otg1x_desc;
0235     struct usb_otg20_descriptor *otg20_desc;
0236     struct usb_otg_caps *otg_caps = gadget->otg_caps;
0237     u8 otg_attributes = 0;
0238 
0239     if (!otg_desc)
0240         return -EINVAL;
0241 
0242     if (otg_caps && otg_caps->otg_rev) {
0243         if (otg_caps->hnp_support)
0244             otg_attributes |= USB_OTG_HNP;
0245         if (otg_caps->srp_support)
0246             otg_attributes |= USB_OTG_SRP;
0247         if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200))
0248             otg_attributes |= USB_OTG_ADP;
0249     } else {
0250         otg_attributes = USB_OTG_SRP | USB_OTG_HNP;
0251     }
0252 
0253     if (otg_caps && (otg_caps->otg_rev >= 0x0200)) {
0254         otg20_desc = (struct usb_otg20_descriptor *)otg_desc;
0255         otg20_desc->bLength = sizeof(struct usb_otg20_descriptor);
0256         otg20_desc->bDescriptorType = USB_DT_OTG;
0257         otg20_desc->bmAttributes = otg_attributes;
0258         otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev);
0259     } else {
0260         otg1x_desc = (struct usb_otg_descriptor *)otg_desc;
0261         otg1x_desc->bLength = sizeof(struct usb_otg_descriptor);
0262         otg1x_desc->bDescriptorType = USB_DT_OTG;
0263         otg1x_desc->bmAttributes = otg_attributes;
0264     }
0265 
0266     return 0;
0267 }
0268 EXPORT_SYMBOL_GPL(usb_otg_descriptor_init);