1c40bbd1c959eeeb069f95f3c369363762227029
[reactos.git] / reactos / drivers / usb / cromwell / core / config.c
1 #if 0
2 #include <linux/usb.h>
3 #include <linux/module.h>
4 #include <linux/init.h>
5 #include <linux/slab.h>
6 #include <asm/byteorder.h>
7 #else
8 #include "../usb_wrapper.h"
9 #endif
10
11 #define USB_MAXALTSETTING 128 /* Hard limit */
12 #define USB_MAXENDPOINTS 30 /* Hard limit */
13
14 /* these maximums are arbitrary */
15 #define USB_MAXCONFIG 8
16 #define USB_ALTSETTINGALLOC 4
17 #define USB_MAXINTERFACES 32
18
19 static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char *buffer, int size)
20 {
21 struct usb_descriptor_header *header;
22 unsigned char *begin;
23 int parsed = 0, len, numskipped;
24
25 header = (struct usb_descriptor_header *)buffer;
26
27 /* Everything should be fine being passed into here, but we sanity */
28 /* check JIC */
29 if (header->bLength > size) {
30 err("ran out of descriptors parsing");
31 return -1;
32 }
33
34 if (header->bDescriptorType != USB_DT_ENDPOINT) {
35 warn("unexpected descriptor 0x%X, expecting endpoint, 0x%X",
36 header->bDescriptorType, USB_DT_ENDPOINT);
37 return parsed;
38 }
39
40 if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
41 memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
42 else
43 memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_SIZE);
44
45 le16_to_cpus(&endpoint->desc.wMaxPacketSize);
46
47 buffer += header->bLength;
48 size -= header->bLength;
49 parsed += header->bLength;
50
51 /* Skip over the rest of the Class Specific or Vendor Specific */
52 /* descriptors */
53 begin = buffer;
54 numskipped = 0;
55 while (size >= sizeof(struct usb_descriptor_header)) {
56 header = (struct usb_descriptor_header *)buffer;
57
58 if (header->bLength < 2) {
59 err("invalid descriptor length of %d", header->bLength);
60 return -1;
61 }
62
63 /* If we find another "proper" descriptor then we're done */
64 if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
65 (header->bDescriptorType == USB_DT_INTERFACE) ||
66 (header->bDescriptorType == USB_DT_CONFIG) ||
67 (header->bDescriptorType == USB_DT_DEVICE))
68 break;
69
70 dbg("skipping descriptor 0x%X",
71 header->bDescriptorType);
72 numskipped++;
73
74 buffer += header->bLength;
75 size -= header->bLength;
76 parsed += header->bLength;
77 }
78 if (numskipped)
79 dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
80
81 /* Copy any unknown descriptors into a storage area for drivers */
82 /* to later parse */
83 len = (int)(buffer - begin);
84 if (!len) {
85 endpoint->extra = NULL;
86 endpoint->extralen = 0;
87 return parsed;
88 }
89
90 endpoint->extra = kmalloc(len, GFP_KERNEL);
91
92 if (!endpoint->extra) {
93 err("couldn't allocate memory for endpoint extra descriptors");
94 endpoint->extralen = 0;
95 return parsed;
96 }
97
98 memcpy(endpoint->extra, begin, len);
99 endpoint->extralen = len;
100
101 return parsed;
102 }
103
104 static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size)
105 {
106 int i, len, numskipped, retval, parsed = 0;
107 struct usb_descriptor_header *header;
108 struct usb_host_interface *ifp;
109 unsigned char *begin;
110
111 interface->act_altsetting = 0;
112 interface->num_altsetting = 0;
113 interface->max_altsetting = USB_ALTSETTINGALLOC;
114 device_initialize(&interface->dev);
115
116 interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting,
117 GFP_KERNEL);
118
119 if (!interface->altsetting) {
120 err("couldn't kmalloc interface->altsetting");
121 return -1;
122 }
123
124 while (size > 0) {
125 struct usb_interface_descriptor *d;
126
127 if (interface->num_altsetting >= interface->max_altsetting) {
128 struct usb_host_interface *ptr;
129 int oldmas;
130
131 oldmas = interface->max_altsetting;
132 interface->max_altsetting += USB_ALTSETTINGALLOC;
133 if (interface->max_altsetting > USB_MAXALTSETTING) {
134 warn("too many alternate settings (incr %d max %d)\n",
135 USB_ALTSETTINGALLOC, USB_MAXALTSETTING);
136 return -1;
137 }
138
139 ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL);
140 if (ptr == NULL) {
141 err("couldn't kmalloc interface->altsetting");
142 return -1;
143 }
144 memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas);
145 kfree(interface->altsetting);
146 interface->altsetting = ptr;
147 }
148
149 ifp = interface->altsetting + interface->num_altsetting;
150 ifp->endpoint = NULL;
151 ifp->extra = NULL;
152 ifp->extralen = 0;
153 interface->num_altsetting++;
154
155 memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
156
157 /* Skip over the interface */
158 buffer += ifp->desc.bLength;
159 parsed += ifp->desc.bLength;
160 size -= ifp->desc.bLength;
161
162 begin = buffer;
163 numskipped = 0;
164
165 /* Skip over any interface, class or vendor descriptors */
166 while (size >= sizeof(struct usb_descriptor_header)) {
167 header = (struct usb_descriptor_header *)buffer;
168
169 if (header->bLength < 2) {
170 err("invalid descriptor length of %d", header->bLength);
171 return -1;
172 }
173
174 /* If we find another "proper" descriptor then we're done */
175 if ((header->bDescriptorType == USB_DT_INTERFACE) ||
176 (header->bDescriptorType == USB_DT_ENDPOINT) ||
177 (header->bDescriptorType == USB_DT_CONFIG) ||
178 (header->bDescriptorType == USB_DT_DEVICE))
179 break;
180
181 numskipped++;
182
183 buffer += header->bLength;
184 parsed += header->bLength;
185 size -= header->bLength;
186 }
187
188 if (numskipped)
189 dbg("skipped %d class/vendor specific interface descriptors", numskipped);
190
191 /* Copy any unknown descriptors into a storage area for */
192 /* drivers to later parse */
193 len = (int)(buffer - begin);
194 if (len) {
195 ifp->extra = kmalloc(len, GFP_KERNEL);
196
197 if (!ifp->extra) {
198 err("couldn't allocate memory for interface extra descriptors");
199 ifp->extralen = 0;
200 return -1;
201 }
202 memcpy(ifp->extra, begin, len);
203 ifp->extralen = len;
204 }
205
206 /* Did we hit an unexpected descriptor? */
207 header = (struct usb_descriptor_header *)buffer;
208 if ((size >= sizeof(struct usb_descriptor_header)) &&
209 ((header->bDescriptorType == USB_DT_CONFIG) ||
210 (header->bDescriptorType == USB_DT_DEVICE)))
211 return parsed;
212
213 if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) {
214 warn("too many endpoints");
215 return -1;
216 }
217
218 ifp->endpoint = (struct usb_host_endpoint *)
219 kmalloc(ifp->desc.bNumEndpoints *
220 sizeof(struct usb_host_endpoint), GFP_KERNEL);
221 if (!ifp->endpoint) {
222 err("out of memory");
223 return -1;
224 }
225
226 memset(ifp->endpoint, 0, ifp->desc.bNumEndpoints *
227 sizeof(struct usb_host_endpoint));
228
229 for (i = 0; i < ifp->desc.bNumEndpoints; i++) {
230 header = (struct usb_descriptor_header *)buffer;
231
232 if (header->bLength > size) {
233 err("ran out of descriptors parsing");
234 return -1;
235 }
236
237 retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
238 if (retval < 0)
239 return retval;
240
241 buffer += retval;
242 parsed += retval;
243 size -= retval;
244 }
245
246 /* We check to see if it's an alternate to this one */
247 d = (struct usb_interface_descriptor *)buffer;
248 if (size < USB_DT_INTERFACE_SIZE
249 || d->bDescriptorType != USB_DT_INTERFACE
250 || !d->bAlternateSetting)
251 return parsed;
252 }
253
254 return parsed;
255 }
256
257 int usb_parse_configuration(struct usb_host_config *config, char *buffer)
258 {
259 int i, retval, size;
260 struct usb_descriptor_header *header;
261
262 memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
263 le16_to_cpus(&config->desc.wTotalLength);
264 size = config->desc.wTotalLength;
265
266 if (config->desc.bNumInterfaces > USB_MAXINTERFACES) {
267 warn("too many interfaces");
268 return -1;
269 }
270
271 config->interface = (struct usb_interface *)
272 kmalloc(config->desc.bNumInterfaces *
273 sizeof(struct usb_interface), GFP_KERNEL);
274 dbg("kmalloc IF %p, numif %i", config->interface, config->desc.bNumInterfaces);
275 if (!config->interface) {
276 err("out of memory");
277 return -1;
278 }
279
280 memset(config->interface, 0,
281 config->desc.bNumInterfaces * sizeof(struct usb_interface));
282
283 buffer += config->desc.bLength;
284 size -= config->desc.bLength;
285
286 config->extra = NULL;
287 config->extralen = 0;
288
289 for (i = 0; i < config->desc.bNumInterfaces; i++) {
290 int numskipped, len;
291 char *begin;
292
293 /* Skip over the rest of the Class Specific or Vendor */
294 /* Specific descriptors */
295 begin = buffer;
296 numskipped = 0;
297 while (size >= sizeof(struct usb_descriptor_header)) {
298 header = (struct usb_descriptor_header *)buffer;
299
300 if ((header->bLength > size) || (header->bLength < 2)) {
301 err("invalid descriptor length of %d", header->bLength);
302 return -1;
303 }
304
305 /* If we find another "proper" descriptor then we're done */
306 if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
307 (header->bDescriptorType == USB_DT_INTERFACE) ||
308 (header->bDescriptorType == USB_DT_CONFIG) ||
309 (header->bDescriptorType == USB_DT_DEVICE))
310 break;
311
312 dbg("skipping descriptor 0x%X", header->bDescriptorType);
313 numskipped++;
314
315 buffer += header->bLength;
316 size -= header->bLength;
317 }
318 if (numskipped)
319 dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
320
321 /* Copy any unknown descriptors into a storage area for */
322 /* drivers to later parse */
323 len = (int)(buffer - begin);
324 if (len) {
325 if (config->extralen) {
326 warn("extra config descriptor");
327 } else {
328 config->extra = kmalloc(len, GFP_KERNEL);
329 if (!config->extra) {
330 err("couldn't allocate memory for config extra descriptors");
331 config->extralen = 0;
332 return -1;
333 }
334
335 memcpy(config->extra, begin, len);
336 config->extralen = len;
337 }
338 }
339
340 retval = usb_parse_interface(config->interface + i, buffer, size);
341 if (retval < 0)
342 return retval;
343
344 buffer += retval;
345 size -= retval;
346 }
347
348 return size;
349 }
350
351 // hub-only!! ... and only exported for reset/reinit path.
352 // otherwise used internally on disconnect/destroy path
353 void usb_destroy_configuration(struct usb_device *dev)
354 {
355 int c, i, j, k;
356
357 if (!dev->config)
358 return;
359
360 if (dev->rawdescriptors) {
361 for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
362 kfree(dev->rawdescriptors[i]);
363
364 kfree(dev->rawdescriptors);
365 }
366
367 for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
368 struct usb_host_config *cf = &dev->config[c];
369
370 if (!cf->interface)
371 break;
372
373 for (i = 0; i < cf->desc.bNumInterfaces; i++) {
374 struct usb_interface *ifp =
375 &cf->interface[i];
376
377 if (!ifp->altsetting)
378 break;
379
380 for (j = 0; j < ifp->num_altsetting; j++) {
381 struct usb_host_interface *as =
382 &ifp->altsetting[j];
383
384 if(as->extra) {
385 kfree(as->extra);
386 }
387
388 if (!as->endpoint)
389 break;
390
391 for(k = 0; k < as->desc.bNumEndpoints; k++) {
392 if(as->endpoint[k].extra) {
393 kfree(as->endpoint[k].extra);
394 }
395 }
396 kfree(as->endpoint);
397 }
398
399 kfree(ifp->altsetting);
400 }
401 kfree(cf->interface);
402 }
403 kfree(dev->config);
404 }
405
406
407 // hub-only!! ... and only in reset path, or usb_new_device()
408 // (used by real hubs and virtual root hubs)
409 int usb_get_configuration(struct usb_device *dev)
410 {
411 int result;
412 unsigned int cfgno, length;
413 unsigned char *buffer;
414 unsigned char *bigbuffer;
415 struct usb_config_descriptor *desc;
416
417 if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
418 warn("too many configurations");
419 return -EINVAL;
420 }
421
422 if (dev->descriptor.bNumConfigurations < 1) {
423 warn("not enough configurations");
424 return -EINVAL;
425 }
426
427 dev->config = (struct usb_host_config *)
428 kmalloc(dev->descriptor.bNumConfigurations *
429 sizeof(struct usb_host_config), GFP_KERNEL);
430 if (!dev->config) {
431 err("out of memory");
432 return -ENOMEM;
433 }
434 memset(dev->config, 0, dev->descriptor.bNumConfigurations *
435 sizeof(struct usb_host_config));
436
437 dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
438 dev->descriptor.bNumConfigurations, GFP_KERNEL);
439 if (!dev->rawdescriptors) {
440 err("out of memory");
441 return -ENOMEM;
442 }
443
444 buffer = kmalloc(8, GFP_KERNEL);
445 if (!buffer) {
446 err("unable to allocate memory for configuration descriptors");
447 return -ENOMEM;
448 }
449 desc = (struct usb_config_descriptor *)buffer;
450
451 for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
452 /* We grab the first 8 bytes so we know how long the whole */
453 /* configuration is */
454 result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
455 if (result < 8) {
456 if (result < 0)
457 err("unable to get descriptor");
458 else {
459 err("config descriptor too short (expected %i, got %i)", 8, result);
460 result = -EINVAL;
461 }
462 goto err;
463 }
464
465 /* Get the full buffer */
466 length = le16_to_cpu(desc->wTotalLength);
467
468 bigbuffer = kmalloc(length, GFP_KERNEL);
469 if (!bigbuffer) {
470 err("unable to allocate memory for configuration descriptors");
471 result = -ENOMEM;
472 goto err;
473 }
474
475 /* Now that we know the length, get the whole thing */
476 result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
477 if (result < 0) {
478 err("couldn't get all of config descriptors");
479 kfree(bigbuffer);
480 goto err;
481 }
482
483 if (result < length) {
484 err("config descriptor too short (expected %i, got %i)", length, result);
485 result = -EINVAL;
486 kfree(bigbuffer);
487 goto err;
488 }
489
490 dev->rawdescriptors[cfgno] = bigbuffer;
491
492 result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
493 if (result > 0)
494 dbg("descriptor data left");
495 else if (result < 0) {
496 result = -EINVAL;
497 goto err;
498 }
499 }
500
501 kfree(buffer);
502 return 0;
503 err:
504 kfree(buffer);
505 dev->descriptor.bNumConfigurations = cfgno;
506 return result;
507 }
508