|
@@ -96,7 +96,7 @@ int usb_gadget_config_buf(
|
|
|
/* 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,
|
|
@@ -115,3 +115,77 @@ int usb_gadget_config_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;
|
|
|
+}
|