diff options
Diffstat (limited to 'drivers/usb/gadget/config.c')
-rw-r--r-- | drivers/usb/gadget/config.c | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index a4e54b2743f0..1ca1c326392a 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c | |||
@@ -96,7 +96,7 @@ int usb_gadget_config_buf( | |||
96 | /* config descriptor first */ | 96 | /* config descriptor first */ |
97 | if (length < USB_DT_CONFIG_SIZE || !desc) | 97 | if (length < USB_DT_CONFIG_SIZE || !desc) |
98 | return -EINVAL; | 98 | return -EINVAL; |
99 | *cp = *config; | 99 | *cp = *config; |
100 | 100 | ||
101 | /* then interface/endpoint/class/vendor/... */ | 101 | /* then interface/endpoint/class/vendor/... */ |
102 | len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, | 102 | len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, |
@@ -115,3 +115,77 @@ int usb_gadget_config_buf( | |||
115 | return len; | 115 | return len; |
116 | } | 116 | } |
117 | 117 | ||
118 | /** | ||
119 | * usb_copy_descriptors - copy a vector of USB descriptors | ||
120 | * @src: null-terminated vector to copy | ||
121 | * Context: initialization code, which may sleep | ||
122 | * | ||
123 | * This makes a copy of a vector of USB descriptors. Its primary use | ||
124 | * is to support usb_function objects which can have multiple copies, | ||
125 | * each needing different descriptors. Functions may have static | ||
126 | * tables of descriptors, which are used as templates and customized | ||
127 | * with identifiers (for interfaces, strings, endpoints, and more) | ||
128 | * as needed by a given function instance. | ||
129 | */ | ||
130 | struct usb_descriptor_header **__init | ||
131 | usb_copy_descriptors(struct usb_descriptor_header **src) | ||
132 | { | ||
133 | struct usb_descriptor_header **tmp; | ||
134 | unsigned bytes; | ||
135 | unsigned n_desc; | ||
136 | void *mem; | ||
137 | struct usb_descriptor_header **ret; | ||
138 | |||
139 | /* count descriptors and their sizes; then add vector size */ | ||
140 | for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) | ||
141 | bytes += (*tmp)->bLength; | ||
142 | bytes += (n_desc + 1) * sizeof(*tmp); | ||
143 | |||
144 | mem = kmalloc(bytes, GFP_KERNEL); | ||
145 | if (!mem) | ||
146 | return NULL; | ||
147 | |||
148 | /* fill in pointers starting at "tmp", | ||
149 | * to descriptors copied starting at "mem"; | ||
150 | * and return "ret" | ||
151 | */ | ||
152 | tmp = mem; | ||
153 | ret = mem; | ||
154 | mem += (n_desc + 1) * sizeof(*tmp); | ||
155 | while (*src) { | ||
156 | memcpy(mem, *src, (*src)->bLength); | ||
157 | *tmp = mem; | ||
158 | tmp++; | ||
159 | mem += (*src)->bLength; | ||
160 | src++; | ||
161 | } | ||
162 | *tmp = NULL; | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * usb_find_endpoint - find a copy of an endpoint descriptor | ||
169 | * @src: original vector of descriptors | ||
170 | * @copy: copy of @src | ||
171 | * @ep: endpoint descriptor found in @src | ||
172 | * | ||
173 | * This returns the copy of the @match descriptor made for @copy. Its | ||
174 | * intended use is to help remembering the endpoint descriptor to use | ||
175 | * when enabling a given endpoint. | ||
176 | */ | ||
177 | struct usb_endpoint_descriptor *__init | ||
178 | usb_find_endpoint( | ||
179 | struct usb_descriptor_header **src, | ||
180 | struct usb_descriptor_header **copy, | ||
181 | struct usb_endpoint_descriptor *match | ||
182 | ) | ||
183 | { | ||
184 | while (*src) { | ||
185 | if (*src == (void *) match) | ||
186 | return (void *)*copy; | ||
187 | src++; | ||
188 | copy++; | ||
189 | } | ||
190 | return NULL; | ||
191 | } | ||