linux/drivers/usb/gadget/config.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * usb/gadget/config.c -- simplify building config descriptors
   4 *
   5 * Copyright (C) 2003 David Brownell
   6 */
   7
   8#include <linux/errno.h>
   9#include <linux/slab.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/list.h>
  13#include <linux/string.h>
  14#include <linux/device.h>
  15
  16#include <linux/usb/ch9.h>
  17#include <linux/usb/gadget.h>
  18#include <linux/usb/composite.h>
  19#include <linux/usb/otg.h>
  20
  21/**
  22 * usb_descriptor_fillbuf - fill buffer with descriptors
  23 * @buf: Buffer to be filled
  24 * @buflen: Size of buf
  25 * @src: Array of descriptor pointers, terminated by null pointer.
  26 *
  27 * Copies descriptors into the buffer, returning the length or a
  28 * negative error code if they can't all be copied.  Useful when
  29 * assembling descriptors for an associated set of interfaces used
  30 * as part of configuring a composite device; or in other cases where
  31 * sets of descriptors need to be marshaled.
  32 */
  33int
  34usb_descriptor_fillbuf(void *buf, unsigned buflen,
  35                const struct usb_descriptor_header **src)
  36{
  37        u8      *dest = buf;
  38
  39        if (!src)
  40                return -EINVAL;
  41
  42        /* fill buffer from src[] until null descriptor ptr */
  43        for (; NULL != *src; src++) {
  44                unsigned                len = (*src)->bLength;
  45
  46                if (len > buflen)
  47                        return -EINVAL;
  48                memcpy(dest, *src, len);
  49                buflen -= len;
  50                dest += len;
  51        }
  52        return dest - (u8 *)buf;
  53}
  54EXPORT_SYMBOL_GPL(usb_descriptor_fillbuf);
  55
  56/**
  57 * usb_gadget_config_buf - builts a complete configuration descriptor
  58 * @config: Header for the descriptor, including characteristics such
  59 *      as power requirements and number of interfaces.
  60 * @desc: Null-terminated vector of pointers to the descriptors (interface,
  61 *      endpoint, etc) defining all functions in this device configuration.
  62 * @buf: Buffer for the resulting configuration descriptor.
  63 * @length: Length of buffer.  If this is not big enough to hold the
  64 *      entire configuration descriptor, an error code will be returned.
  65 *
  66 * This copies descriptors into the response buffer, building a descriptor
  67 * for that configuration.  It returns the buffer length or a negative
  68 * status code.  The config.wTotalLength field is set to match the length
  69 * of the result, but other descriptor fields (including power usage and
  70 * interface count) must be set by the caller.
  71 *
  72 * Gadget drivers could use this when constructing a config descriptor
  73 * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
  74 * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
  75 */
  76int usb_gadget_config_buf(
  77        const struct usb_config_descriptor      *config,
  78        void                                    *buf,
  79        unsigned                                length,
  80        const struct usb_descriptor_header      **desc
  81)
  82{
  83        struct usb_config_descriptor            *cp = buf;
  84        int                                     len;
  85
  86        /* config descriptor first */
  87        if (length < USB_DT_CONFIG_SIZE || !desc)
  88                return -EINVAL;
  89        *cp = *config;
  90
  91        /* then interface/endpoint/class/vendor/... */
  92        len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8 *)buf,
  93                        length - USB_DT_CONFIG_SIZE, desc);
  94        if (len < 0)
  95                return len;
  96        len += USB_DT_CONFIG_SIZE;
  97        if (len > 0xffff)
  98                return -EINVAL;
  99
 100        /* patch up the config descriptor */
 101        cp->bLength = USB_DT_CONFIG_SIZE;
 102        cp->bDescriptorType = USB_DT_CONFIG;
 103        cp->wTotalLength = cpu_to_le16(len);
 104        cp->bmAttributes |= USB_CONFIG_ATT_ONE;
 105        return len;
 106}
 107EXPORT_SYMBOL_GPL(usb_gadget_config_buf);
 108
 109/**
 110 * usb_copy_descriptors - copy a vector of USB descriptors
 111 * @src: null-terminated vector to copy
 112 * Context: initialization code, which may sleep
 113 *
 114 * This makes a copy of a vector of USB descriptors.  Its primary use
 115 * is to support usb_function objects which can have multiple copies,
 116 * each needing different descriptors.  Functions may have static
 117 * tables of descriptors, which are used as templates and customized
 118 * with identifiers (for interfaces, strings, endpoints, and more)
 119 * as needed by a given function instance.
 120 */
 121struct usb_descriptor_header **
 122usb_copy_descriptors(struct usb_descriptor_header **src)
 123{
 124        struct usb_descriptor_header **tmp;
 125        unsigned bytes;
 126        unsigned n_desc;
 127        void *mem;
 128        struct usb_descriptor_header **ret;
 129
 130        /* count descriptors and their sizes; then add vector size */
 131        for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++)
 132                bytes += (*tmp)->bLength;
 133        bytes += (n_desc + 1) * sizeof(*tmp);
 134
 135        mem = kmalloc(bytes, GFP_KERNEL);
 136        if (!mem)
 137                return NULL;
 138
 139        /* fill in pointers starting at "tmp",
 140         * to descriptors copied starting at "mem";
 141         * and return "ret"
 142         */
 143        tmp = mem;
 144        ret = mem;
 145        mem += (n_desc + 1) * sizeof(*tmp);
 146        while (*src) {
 147                memcpy(mem, *src, (*src)->bLength);
 148                *tmp = mem;
 149                tmp++;
 150                mem += (*src)->bLength;
 151                src++;
 152        }
 153        *tmp = NULL;
 154
 155        return ret;
 156}
 157EXPORT_SYMBOL_GPL(usb_copy_descriptors);
 158
 159int usb_assign_descriptors(struct usb_function *f,
 160                struct usb_descriptor_header **fs,
 161                struct usb_descriptor_header **hs,
 162                struct usb_descriptor_header **ss,
 163                struct usb_descriptor_header **ssp)
 164{
 165        struct usb_gadget *g = f->config->cdev->gadget;
 166
 167        if (fs) {
 168                f->fs_descriptors = usb_copy_descriptors(fs);
 169                if (!f->fs_descriptors)
 170                        goto err;
 171        }
 172        if (hs && gadget_is_dualspeed(g)) {
 173                f->hs_descriptors = usb_copy_descriptors(hs);
 174                if (!f->hs_descriptors)
 175                        goto err;
 176        }
 177        if (ss && gadget_is_superspeed(g)) {
 178                f->ss_descriptors = usb_copy_descriptors(ss);
 179                if (!f->ss_descriptors)
 180                        goto err;
 181        }
 182        if (ssp && gadget_is_superspeed_plus(g)) {
 183                f->ssp_descriptors = usb_copy_descriptors(ssp);
 184                if (!f->ssp_descriptors)
 185                        goto err;
 186        }
 187        return 0;
 188err:
 189        usb_free_all_descriptors(f);
 190        return -ENOMEM;
 191}
 192EXPORT_SYMBOL_GPL(usb_assign_descriptors);
 193
 194void usb_free_all_descriptors(struct usb_function *f)
 195{
 196        usb_free_descriptors(f->fs_descriptors);
 197        usb_free_descriptors(f->hs_descriptors);
 198        usb_free_descriptors(f->ss_descriptors);
 199        usb_free_descriptors(f->ssp_descriptors);
 200}
 201EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
 202
 203struct usb_descriptor_header *usb_otg_descriptor_alloc(
 204                                struct usb_gadget *gadget)
 205{
 206        struct usb_descriptor_header *otg_desc;
 207        unsigned length = 0;
 208
 209        if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200))
 210                length = sizeof(struct usb_otg20_descriptor);
 211        else
 212                length = sizeof(struct usb_otg_descriptor);
 213
 214        otg_desc = kzalloc(length, GFP_KERNEL);
 215        return otg_desc;
 216}
 217EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc);
 218
 219int usb_otg_descriptor_init(struct usb_gadget *gadget,
 220                struct usb_descriptor_header *otg_desc)
 221{
 222        struct usb_otg_descriptor *otg1x_desc;
 223        struct usb_otg20_descriptor *otg20_desc;
 224        struct usb_otg_caps *otg_caps = gadget->otg_caps;
 225        u8 otg_attributes = 0;
 226
 227        if (!otg_desc)
 228                return -EINVAL;
 229
 230        if (otg_caps && otg_caps->otg_rev) {
 231                if (otg_caps->hnp_support)
 232                        otg_attributes |= USB_OTG_HNP;
 233                if (otg_caps->srp_support)
 234                        otg_attributes |= USB_OTG_SRP;
 235                if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200))
 236                        otg_attributes |= USB_OTG_ADP;
 237        } else {
 238                otg_attributes = USB_OTG_SRP | USB_OTG_HNP;
 239        }
 240
 241        if (otg_caps && (otg_caps->otg_rev >= 0x0200)) {
 242                otg20_desc = (struct usb_otg20_descriptor *)otg_desc;
 243                otg20_desc->bLength = sizeof(struct usb_otg20_descriptor);
 244                otg20_desc->bDescriptorType = USB_DT_OTG;
 245                otg20_desc->bmAttributes = otg_attributes;
 246                otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev);
 247        } else {
 248                otg1x_desc = (struct usb_otg_descriptor *)otg_desc;
 249                otg1x_desc->bLength = sizeof(struct usb_otg_descriptor);
 250                otg1x_desc->bDescriptorType = USB_DT_OTG;
 251                otg1x_desc->bmAttributes = otg_attributes;
 252        }
 253
 254        return 0;
 255}
 256EXPORT_SYMBOL_GPL(usb_otg_descriptor_init);
 257