/* config descriptor first */
        if (length < USB_DT_CONFIG_SIZE || !desc)
                return -EINVAL;
-       *cp = *config; 
+       *cp = *config;
 
        /* then interface/endpoint/class/vendor/... */
        len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
        return len;
 }
 
+/**
+ * usb_copy_descriptors - copy a vector of USB descriptors
+ * @src: null-terminated vector to copy
+ * Context: initialization code, which may sleep
+ *
+ * This makes a copy of a vector of USB descriptors.  Its primary use
+ * is to support usb_function objects which can have multiple copies,
+ * each needing different descriptors.  Functions may have static
+ * tables of descriptors, which are used as templates and customized
+ * with identifiers (for interfaces, strings, endpoints, and more)
+ * as needed by a given function instance.
+ */
+struct usb_descriptor_header **__init
+usb_copy_descriptors(struct usb_descriptor_header **src)
+{
+       struct usb_descriptor_header **tmp;
+       unsigned bytes;
+       unsigned n_desc;
+       void *mem;
+       struct usb_descriptor_header **ret;
+
+       /* count descriptors and their sizes; then add vector size */
+       for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++)
+               bytes += (*tmp)->bLength;
+       bytes += (n_desc + 1) * sizeof(*tmp);
+
+       mem = kmalloc(bytes, GFP_KERNEL);
+       if (!mem)
+               return NULL;
+
+       /* fill in pointers starting at "tmp",
+        * to descriptors copied starting at "mem";
+        * and return "ret"
+        */
+       tmp = mem;
+       ret = mem;
+       mem += (n_desc + 1) * sizeof(*tmp);
+       while (*src) {
+               memcpy(mem, *src, (*src)->bLength);
+               *tmp = mem;
+               tmp++;
+               mem += (*src)->bLength;
+               src++;
+       }
+       *tmp = NULL;
+
+       return ret;
+}
+
+/**
+ * usb_find_endpoint - find a copy of an endpoint descriptor
+ * @src: original vector of descriptors
+ * @copy: copy of @src
+ * @ep: endpoint descriptor found in @src
+ *
+ * This returns the copy of the @match descriptor made for @copy.  Its
+ * intended use is to help remembering the endpoint descriptor to use
+ * when enabling a given endpoint.
+ */
+struct usb_endpoint_descriptor *__init
+usb_find_endpoint(
+       struct usb_descriptor_header **src,
+       struct usb_descriptor_header **copy,
+       struct usb_endpoint_descriptor *match
+)
+{
+       while (*src) {
+               if (*src == (void *) match)
+                       return (void *)*copy;
+               src++;
+               copy++;
+       }
+       return NULL;
+}
 
 int usb_gadget_config_buf(const struct usb_config_descriptor *config,
        void *buf, unsigned buflen, const struct usb_descriptor_header **desc);
 
+/* copy a NULL-terminated vector of descriptors */
+struct usb_descriptor_header **usb_copy_descriptors(
+               struct usb_descriptor_header **);
+
+/* return copy of endpoint descriptor given original descriptor set */
+struct usb_endpoint_descriptor *usb_find_endpoint(
+       struct usb_descriptor_header **src,
+       struct usb_descriptor_header **copy,
+       struct usb_endpoint_descriptor *match);
+
+/**
+ * usb_free_descriptors - free descriptors returned by usb_copy_descriptors()
+ * @v: vector of descriptors
+ */
+static inline void usb_free_descriptors(struct usb_descriptor_header **v)
+{
+       kfree(v);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* utility wrapping a simple endpoint selection policy */