1 | /*
|
---|
2 | * Parses descriptors
|
---|
3 | *
|
---|
4 | * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
|
---|
5 | *
|
---|
6 | * This library is covered by the LGPL, read LICENSE for details.
|
---|
7 | */
|
---|
8 |
|
---|
9 | #include <stdio.h>
|
---|
10 | #include <string.h>
|
---|
11 | #include "usbi.h"
|
---|
12 |
|
---|
13 | int usb_get_descriptor_by_endpoint(usb_dev_handle *udev, int ep,
|
---|
14 | unsigned char type, unsigned char index, void *buf, int size)
|
---|
15 | {
|
---|
16 | memset(buf, 0, size);
|
---|
17 |
|
---|
18 | return usb_control_msg(udev, ep | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
---|
19 | (type << 8) + index, 0, buf, size, 1000);
|
---|
20 | }
|
---|
21 |
|
---|
22 | int usb_get_descriptor(usb_dev_handle *udev, unsigned char type,
|
---|
23 | unsigned char index, void *buf, int size)
|
---|
24 | {
|
---|
25 | memset(buf, 0, size);
|
---|
26 |
|
---|
27 | return usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
---|
28 | (type << 8) + index, 0, buf, size, 1000);
|
---|
29 | }
|
---|
30 |
|
---|
31 | int usb_parse_descriptor(unsigned char *source, char *description, void *dest)
|
---|
32 | {
|
---|
33 | unsigned char *sp = source, *dp = dest;
|
---|
34 | uint16_t w;
|
---|
35 | uint32_t d;
|
---|
36 | char *cp;
|
---|
37 |
|
---|
38 | for (cp = description; *cp; cp++)
|
---|
39 | {
|
---|
40 | switch (*cp)
|
---|
41 | {
|
---|
42 | case 'b': /* 8-bit byte */
|
---|
43 | *dp++ = *sp++;
|
---|
44 | break;
|
---|
45 | case 'w': /* 16-bit word, convert from little endian to CPU */
|
---|
46 | w = (sp[1] << 8) | sp[0];
|
---|
47 | sp += 2;
|
---|
48 | //dp += ((unsigned long)dp & 1); /* Align to word boundary */
|
---|
49 | *((uint16_t *)dp) = w;
|
---|
50 | dp += 2;
|
---|
51 | break;
|
---|
52 | case 'd': /* 32-bit dword, convert from little endian to CPU */
|
---|
53 | d = (sp[3] << 24) | (sp[2] << 16) | (sp[1] << 8) | sp[0];
|
---|
54 | sp += 4;
|
---|
55 | //dp += ((unsigned long)dp & 2); /* Align to dword boundary */
|
---|
56 | *((uint32_t *)dp) = d;
|
---|
57 | dp += 4;
|
---|
58 | break;
|
---|
59 | /* These two characters are undocumented and just a hack for Linux */
|
---|
60 | case 'W': /* 16-bit word, keep CPU endianess */
|
---|
61 | //dp += ((unsigned long)dp & 1); /* Align to word boundary */
|
---|
62 | memcpy(dp, sp, 2);
|
---|
63 | sp += 2;
|
---|
64 | dp += 2;
|
---|
65 | break;
|
---|
66 | case 'D': /* 32-bit dword, keep CPU endianess */
|
---|
67 | //dp += ((unsigned long)dp & 2); /* Align to dword boundary */
|
---|
68 | memcpy(dp, sp, 4);
|
---|
69 | sp += 4;
|
---|
70 | dp += 4;
|
---|
71 | break;
|
---|
72 | }
|
---|
73 | }
|
---|
74 |
|
---|
75 | return (int)(sp - source);
|
---|
76 | }
|
---|
77 |
|
---|
78 | /*
|
---|
79 | * This code looks surprisingly similar to the code I wrote for the Linux
|
---|
80 | * kernel. It's not a coincidence :)
|
---|
81 | */
|
---|
82 |
|
---|
83 | static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
|
---|
84 | {
|
---|
85 | struct usb_descriptor_header header;
|
---|
86 | unsigned char *begin;
|
---|
87 | int parsed = 0, len, numskipped;
|
---|
88 |
|
---|
89 | usb_parse_descriptor(buffer, "bb", &header);
|
---|
90 |
|
---|
91 | /* Everything should be fine being passed into here, but we sanity */
|
---|
92 | /* check JIC */
|
---|
93 | if (header.bLength > size)
|
---|
94 | {
|
---|
95 | if (usb_debug >= 1)
|
---|
96 | fprintf(stderr, "ran out of descriptors parsing\n");
|
---|
97 | return -1;
|
---|
98 | }
|
---|
99 |
|
---|
100 | if (header.bDescriptorType != USB_DT_ENDPOINT)
|
---|
101 | {
|
---|
102 | if (usb_debug >= 2)
|
---|
103 | fprintf(stderr, "unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X\n",
|
---|
104 | header.bDescriptorType, USB_DT_ENDPOINT);
|
---|
105 | return parsed;
|
---|
106 | }
|
---|
107 |
|
---|
108 | if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)
|
---|
109 | usb_parse_descriptor(buffer, "bbbbwbbb", endpoint);
|
---|
110 | else if (header.bLength >= ENDPOINT_DESC_LENGTH)
|
---|
111 | usb_parse_descriptor(buffer, "bbbbwb", endpoint);
|
---|
112 |
|
---|
113 | buffer += header.bLength;
|
---|
114 | size -= header.bLength;
|
---|
115 | parsed += header.bLength;
|
---|
116 |
|
---|
117 | /* Skip over the rest of the Class Specific or Vendor Specific */
|
---|
118 | /* descriptors */
|
---|
119 | begin = buffer;
|
---|
120 | numskipped = 0;
|
---|
121 | while (size >= DESC_HEADER_LENGTH)
|
---|
122 | {
|
---|
123 | usb_parse_descriptor(buffer, "bb", &header);
|
---|
124 |
|
---|
125 | if (header.bLength < 2)
|
---|
126 | {
|
---|
127 | if (usb_debug >= 1)
|
---|
128 | fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
|
---|
129 | return -1;
|
---|
130 | }
|
---|
131 |
|
---|
132 | /* If we find another "proper" descriptor then we're done */
|
---|
133 | if ((header.bDescriptorType == USB_DT_ENDPOINT) ||
|
---|
134 | (header.bDescriptorType == USB_DT_INTERFACE) ||
|
---|
135 | (header.bDescriptorType == USB_DT_CONFIG) ||
|
---|
136 | (header.bDescriptorType == USB_DT_DEVICE))
|
---|
137 | break;
|
---|
138 |
|
---|
139 | if (usb_debug >= 1)
|
---|
140 | fprintf(stderr, "skipping descriptor 0x%X\n", header.bDescriptorType);
|
---|
141 | numskipped++;
|
---|
142 |
|
---|
143 | buffer += header.bLength;
|
---|
144 | size -= header.bLength;
|
---|
145 | parsed += header.bLength;
|
---|
146 | }
|
---|
147 |
|
---|
148 | if (numskipped && usb_debug >= 2)
|
---|
149 | fprintf(stderr, "skipped %d class/vendor specific endpoint descriptors\n", numskipped);
|
---|
150 |
|
---|
151 | /* Copy any unknown descriptors into a storage area for drivers */
|
---|
152 | /* to later parse */
|
---|
153 | len = (int)(buffer - begin);
|
---|
154 | if (!len)
|
---|
155 | {
|
---|
156 | endpoint->extra = NULL;
|
---|
157 | endpoint->extralen = 0;
|
---|
158 | return parsed;
|
---|
159 | }
|
---|
160 |
|
---|
161 | endpoint->extra = malloc(len);
|
---|
162 | if (!endpoint->extra)
|
---|
163 | {
|
---|
164 | if (usb_debug >= 1)
|
---|
165 | fprintf(stderr, "couldn't allocate memory for endpoint extra descriptors\n");
|
---|
166 | endpoint->extralen = 0;
|
---|
167 | return parsed;
|
---|
168 | }
|
---|
169 |
|
---|
170 | memcpy(endpoint->extra, begin, len);
|
---|
171 | endpoint->extralen = len;
|
---|
172 |
|
---|
173 | return parsed;
|
---|
174 | }
|
---|
175 |
|
---|
176 | static int usb_parse_interface(struct usb_interface *interface,
|
---|
177 | unsigned char *buffer, int size)
|
---|
178 | {
|
---|
179 | int i, len, numskipped, retval, parsed = 0;
|
---|
180 | struct usb_descriptor_header header;
|
---|
181 | struct usb_interface_descriptor *ifp;
|
---|
182 | unsigned char *begin;
|
---|
183 |
|
---|
184 | interface->num_altsetting = 0;
|
---|
185 |
|
---|
186 | while (size >= INTERFACE_DESC_LENGTH)
|
---|
187 | {
|
---|
188 | interface->altsetting = realloc(interface->altsetting, sizeof(struct usb_interface_descriptor) * (interface->num_altsetting + 1));
|
---|
189 | if (!interface->altsetting)
|
---|
190 | {
|
---|
191 | if (usb_debug >= 1)
|
---|
192 | fprintf(stderr, "couldn't malloc interface->altsetting\n");
|
---|
193 | return -1;
|
---|
194 | }
|
---|
195 |
|
---|
196 | ifp = interface->altsetting + interface->num_altsetting;
|
---|
197 | interface->num_altsetting++;
|
---|
198 |
|
---|
199 | usb_parse_descriptor(buffer, "bbbbbbbbb", ifp);
|
---|
200 |
|
---|
201 | /* Skip over the interface */
|
---|
202 | buffer += ifp->bLength;
|
---|
203 | parsed += ifp->bLength;
|
---|
204 | size -= ifp->bLength;
|
---|
205 |
|
---|
206 | begin = buffer;
|
---|
207 | numskipped = 0;
|
---|
208 |
|
---|
209 | /* Skip over any interface, class or vendor descriptors */
|
---|
210 | while (size >= DESC_HEADER_LENGTH)
|
---|
211 | {
|
---|
212 | usb_parse_descriptor(buffer, "bb", &header);
|
---|
213 |
|
---|
214 | if (header.bLength < 2)
|
---|
215 | {
|
---|
216 | if (usb_debug >= 1)
|
---|
217 | fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
|
---|
218 | return -1;
|
---|
219 | }
|
---|
220 |
|
---|
221 | /* If we find another "proper" descriptor then we're done */
|
---|
222 | if ((header.bDescriptorType == USB_DT_INTERFACE) ||
|
---|
223 | (header.bDescriptorType == USB_DT_ENDPOINT) ||
|
---|
224 | (header.bDescriptorType == USB_DT_CONFIG) ||
|
---|
225 | (header.bDescriptorType == USB_DT_DEVICE))
|
---|
226 | break;
|
---|
227 |
|
---|
228 | numskipped++;
|
---|
229 |
|
---|
230 | buffer += header.bLength;
|
---|
231 | parsed += header.bLength;
|
---|
232 | size -= header.bLength;
|
---|
233 | }
|
---|
234 |
|
---|
235 | if (numskipped && usb_debug >= 2)
|
---|
236 | fprintf(stderr, "skipped %d class/vendor specific interface descriptors\n", numskipped);
|
---|
237 |
|
---|
238 | /* Copy any unknown descriptors into a storage area for */
|
---|
239 | /* drivers to later parse */
|
---|
240 | len = (int)(buffer - begin);
|
---|
241 | if (!len)
|
---|
242 | {
|
---|
243 | ifp->extra = NULL;
|
---|
244 | ifp->extralen = 0;
|
---|
245 | }
|
---|
246 | else
|
---|
247 | {
|
---|
248 | ifp->extra = malloc(len);
|
---|
249 | if (!ifp->extra)
|
---|
250 | {
|
---|
251 | if (usb_debug >= 1)
|
---|
252 | fprintf(stderr, "couldn't allocate memory for interface extra descriptors\n");
|
---|
253 | ifp->extralen = 0;
|
---|
254 | return -1;
|
---|
255 | }
|
---|
256 | memcpy(ifp->extra, begin, len);
|
---|
257 | ifp->extralen = len;
|
---|
258 | }
|
---|
259 |
|
---|
260 | /* Did we hit an unexpected descriptor? */
|
---|
261 | usb_parse_descriptor(buffer, "bb", &header);
|
---|
262 | if ((size >= DESC_HEADER_LENGTH) &&
|
---|
263 | ((header.bDescriptorType == USB_DT_CONFIG) ||
|
---|
264 | (header.bDescriptorType == USB_DT_DEVICE)))
|
---|
265 | return parsed;
|
---|
266 |
|
---|
267 | if (ifp->bNumEndpoints > USB_MAXENDPOINTS)
|
---|
268 | {
|
---|
269 | if (usb_debug >= 1)
|
---|
270 | fprintf(stderr, "too many endpoints\n");
|
---|
271 | return -1;
|
---|
272 | }
|
---|
273 |
|
---|
274 | if (ifp->bNumEndpoints > 0)
|
---|
275 | {
|
---|
276 | ifp->endpoint = (struct usb_endpoint_descriptor *)
|
---|
277 | malloc(ifp->bNumEndpoints *
|
---|
278 | sizeof(struct usb_endpoint_descriptor));
|
---|
279 | if (!ifp->endpoint)
|
---|
280 | {
|
---|
281 | if (usb_debug >= 1)
|
---|
282 | fprintf(stderr, "couldn't allocate memory for ifp->endpoint\n");
|
---|
283 | return -1;
|
---|
284 | }
|
---|
285 |
|
---|
286 | memset(ifp->endpoint, 0, ifp->bNumEndpoints *
|
---|
287 | sizeof(struct usb_endpoint_descriptor));
|
---|
288 |
|
---|
289 | for (i = 0; i < ifp->bNumEndpoints; i++)
|
---|
290 | {
|
---|
291 | usb_parse_descriptor(buffer, "bb", &header);
|
---|
292 |
|
---|
293 | if (header.bLength > size)
|
---|
294 | {
|
---|
295 | if (usb_debug >= 1)
|
---|
296 | fprintf(stderr, "ran out of descriptors parsing\n");
|
---|
297 | return -1;
|
---|
298 | }
|
---|
299 |
|
---|
300 | retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
|
---|
301 | if (retval < 0)
|
---|
302 | return retval;
|
---|
303 |
|
---|
304 | buffer += retval;
|
---|
305 | parsed += retval;
|
---|
306 | size -= retval;
|
---|
307 | }
|
---|
308 | }
|
---|
309 | else
|
---|
310 | ifp->endpoint = NULL;
|
---|
311 |
|
---|
312 | /* We check to see if it's an alternate to this one */
|
---|
313 | ifp = (struct usb_interface_descriptor *)buffer;
|
---|
314 | if (size < USB_DT_INTERFACE_SIZE ||
|
---|
315 | ifp->bDescriptorType != USB_DT_INTERFACE ||
|
---|
316 | !ifp->bAlternateSetting)
|
---|
317 | return parsed;
|
---|
318 | }
|
---|
319 |
|
---|
320 | return parsed;
|
---|
321 | }
|
---|
322 |
|
---|
323 | int usb_parse_configuration(struct usb_config_descriptor *config,
|
---|
324 | unsigned char *buffer)
|
---|
325 | {
|
---|
326 | int i, retval, size;
|
---|
327 | struct usb_descriptor_header header;
|
---|
328 |
|
---|
329 | usb_parse_descriptor(buffer, "bbwbbbbb", config);
|
---|
330 | size = config->wTotalLength;
|
---|
331 |
|
---|
332 | if (config->bNumInterfaces > USB_MAXINTERFACES)
|
---|
333 | {
|
---|
334 | if (usb_debug >= 1)
|
---|
335 | fprintf(stderr, "too many interfaces\n");
|
---|
336 | return -1;
|
---|
337 | }
|
---|
338 |
|
---|
339 | config->interface = (struct usb_interface *)
|
---|
340 | malloc(config->bNumInterfaces *
|
---|
341 | sizeof(struct usb_interface));
|
---|
342 | if (!config->interface)
|
---|
343 | {
|
---|
344 | if (usb_debug >= 1)
|
---|
345 | fprintf(stderr, "out of memory\n");
|
---|
346 | return -1;
|
---|
347 | }
|
---|
348 |
|
---|
349 | memset(config->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface));
|
---|
350 |
|
---|
351 | buffer += config->bLength;
|
---|
352 | size -= config->bLength;
|
---|
353 |
|
---|
354 | config->extra = NULL;
|
---|
355 | config->extralen = 0;
|
---|
356 |
|
---|
357 | for (i = 0; i < config->bNumInterfaces; i++)
|
---|
358 | {
|
---|
359 | int numskipped, len;
|
---|
360 | unsigned char *begin;
|
---|
361 |
|
---|
362 | /* Skip over the rest of the Class Specific or Vendor */
|
---|
363 | /* Specific descriptors */
|
---|
364 | begin = buffer;
|
---|
365 | numskipped = 0;
|
---|
366 | while (size >= DESC_HEADER_LENGTH)
|
---|
367 | {
|
---|
368 | usb_parse_descriptor(buffer, "bb", &header);
|
---|
369 |
|
---|
370 | if ((header.bLength > size) || (header.bLength < DESC_HEADER_LENGTH))
|
---|
371 | {
|
---|
372 | if (usb_debug >= 1)
|
---|
373 | fprintf(stderr, "invalid descriptor length of %d\n", header.bLength);
|
---|
374 | return -1;
|
---|
375 | }
|
---|
376 |
|
---|
377 | /* If we find another "proper" descriptor then we're done */
|
---|
378 | if ((header.bDescriptorType == USB_DT_ENDPOINT) ||
|
---|
379 | (header.bDescriptorType == USB_DT_INTERFACE) ||
|
---|
380 | (header.bDescriptorType == USB_DT_CONFIG) ||
|
---|
381 | (header.bDescriptorType == USB_DT_DEVICE))
|
---|
382 | break;
|
---|
383 |
|
---|
384 | if (usb_debug >= 2)
|
---|
385 | fprintf(stderr, "skipping descriptor 0x%X\n", header.bDescriptorType);
|
---|
386 | numskipped++;
|
---|
387 |
|
---|
388 | buffer += header.bLength;
|
---|
389 | size -= header.bLength;
|
---|
390 | }
|
---|
391 |
|
---|
392 | if (numskipped && usb_debug >= 2)
|
---|
393 | fprintf(stderr, "skipped %d class/vendor specific endpoint descriptors\n", numskipped);
|
---|
394 |
|
---|
395 | /* Copy any unknown descriptors into a storage area for */
|
---|
396 | /* drivers to later parse */
|
---|
397 | len = (int)(buffer - begin);
|
---|
398 | if (len)
|
---|
399 | {
|
---|
400 | /* FIXME: We should realloc and append here */
|
---|
401 | if (!config->extralen)
|
---|
402 | {
|
---|
403 | config->extra = malloc(len);
|
---|
404 | if (!config->extra)
|
---|
405 | {
|
---|
406 | if (usb_debug >= 1)
|
---|
407 | fprintf(stderr, "couldn't allocate memory for config extra descriptors\n");
|
---|
408 | config->extralen = 0;
|
---|
409 | return -1;
|
---|
410 | }
|
---|
411 |
|
---|
412 | memcpy(config->extra, begin, len);
|
---|
413 | config->extralen = len;
|
---|
414 | }
|
---|
415 | }
|
---|
416 |
|
---|
417 | retval = usb_parse_interface(config->interface + i, buffer, size);
|
---|
418 | if (retval < 0)
|
---|
419 | return retval;
|
---|
420 |
|
---|
421 | buffer += retval;
|
---|
422 | size -= retval;
|
---|
423 | }
|
---|
424 |
|
---|
425 | return size;
|
---|
426 | }
|
---|
427 |
|
---|
428 | void usb_destroy_configuration(struct usb_device *dev)
|
---|
429 | {
|
---|
430 | int c, i, j, k;
|
---|
431 |
|
---|
432 | if (!dev->config)
|
---|
433 | return;
|
---|
434 |
|
---|
435 | for (c = 0; c < dev->descriptor.bNumConfigurations; c++)
|
---|
436 | {
|
---|
437 | struct usb_config_descriptor *cf = &dev->config[c];
|
---|
438 |
|
---|
439 | if (!cf->interface)
|
---|
440 | continue;
|
---|
441 |
|
---|
442 | for (i = 0; i < cf->bNumInterfaces; i++)
|
---|
443 | {
|
---|
444 | struct usb_interface *ifp = &cf->interface[i];
|
---|
445 |
|
---|
446 | if (!ifp->altsetting)
|
---|
447 | continue;
|
---|
448 |
|
---|
449 | for (j = 0; j < ifp->num_altsetting; j++)
|
---|
450 | {
|
---|
451 | struct usb_interface_descriptor *as = &ifp->altsetting[j];
|
---|
452 |
|
---|
453 | if (as->extra)
|
---|
454 | free(as->extra);
|
---|
455 |
|
---|
456 | if (!as->endpoint)
|
---|
457 | continue;
|
---|
458 |
|
---|
459 | for (k = 0; k < as->bNumEndpoints; k++)
|
---|
460 | {
|
---|
461 | if (as->endpoint[k].extra)
|
---|
462 | free(as->endpoint[k].extra);
|
---|
463 | }
|
---|
464 | free(as->endpoint);
|
---|
465 | }
|
---|
466 |
|
---|
467 | free(ifp->altsetting);
|
---|
468 | }
|
---|
469 |
|
---|
470 | free(cf->interface);
|
---|
471 | }
|
---|
472 |
|
---|
473 | free(dev->config);
|
---|
474 | }
|
---|
475 |
|
---|
476 | void usb_fetch_and_parse_descriptors(usb_dev_handle *udev)
|
---|
477 | {
|
---|
478 | struct usb_device *dev = udev->device;
|
---|
479 | int i;
|
---|
480 |
|
---|
481 | if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG)
|
---|
482 | {
|
---|
483 | if (usb_debug >= 1)
|
---|
484 | fprintf(stderr, "Too many configurations (%d > %d)\n", dev->descriptor.bNumConfigurations, USB_MAXCONFIG);
|
---|
485 | return;
|
---|
486 | }
|
---|
487 |
|
---|
488 | if (dev->descriptor.bNumConfigurations < 1)
|
---|
489 | {
|
---|
490 | if (usb_debug >= 1)
|
---|
491 | fprintf(stderr, "Not enough configurations (%d < %d)\n", dev->descriptor.bNumConfigurations, 1);
|
---|
492 | return;
|
---|
493 | }
|
---|
494 |
|
---|
495 | dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor));
|
---|
496 | if (!dev->config)
|
---|
497 | {
|
---|
498 | if (usb_debug >= 1)
|
---|
499 | fprintf(stderr, "Unable to allocate memory for config descriptor\n");
|
---|
500 | return;
|
---|
501 | }
|
---|
502 |
|
---|
503 | memset(dev->config, 0, dev->descriptor.bNumConfigurations *
|
---|
504 | sizeof(struct usb_config_descriptor));
|
---|
505 |
|
---|
506 | for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
|
---|
507 | {
|
---|
508 | unsigned char buffer[USB_DT_CONFIG_SIZE], *bigbuffer;
|
---|
509 | struct usb_config_descriptor config;
|
---|
510 | int res;
|
---|
511 |
|
---|
512 | /* Get the first 8 bytes so we can figure out what the total length is */
|
---|
513 | res = usb_get_descriptor(udev, USB_DT_CONFIG, (unsigned char)i, buffer, USB_DT_CONFIG_SIZE);
|
---|
514 | if (res < USB_DT_CONFIG_SIZE)
|
---|
515 | {
|
---|
516 | if (usb_debug >= 1)
|
---|
517 | {
|
---|
518 | if (res < 0)
|
---|
519 | fprintf(stderr, "Unable to get descriptor (%d)\n", res);
|
---|
520 | else
|
---|
521 | fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", USB_DT_CONFIG_SIZE, res);
|
---|
522 | }
|
---|
523 |
|
---|
524 | goto err;
|
---|
525 | }
|
---|
526 |
|
---|
527 | usb_parse_descriptor(buffer, "bbw", &config);
|
---|
528 |
|
---|
529 | bigbuffer = malloc(config.wTotalLength);
|
---|
530 | if (!bigbuffer)
|
---|
531 | {
|
---|
532 | if (usb_debug >= 1)
|
---|
533 | fprintf(stderr, "Unable to allocate memory for descriptors\n");
|
---|
534 | goto err;
|
---|
535 | }
|
---|
536 |
|
---|
537 | res = usb_get_descriptor(udev, USB_DT_CONFIG, (unsigned char)i, bigbuffer,
|
---|
538 | config.wTotalLength);
|
---|
539 | if (res < config.wTotalLength)
|
---|
540 | {
|
---|
541 | if (usb_debug >= 1)
|
---|
542 | {
|
---|
543 | if (res < 0)
|
---|
544 | fprintf(stderr, "Unable to get descriptor (%d)\n", res);
|
---|
545 | else
|
---|
546 | fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, res);
|
---|
547 | }
|
---|
548 |
|
---|
549 | free(bigbuffer);
|
---|
550 | goto err;
|
---|
551 | }
|
---|
552 |
|
---|
553 | res = usb_parse_configuration(&dev->config[i], bigbuffer);
|
---|
554 | if (usb_debug >= 2)
|
---|
555 | {
|
---|
556 | if (res > 0)
|
---|
557 | fprintf(stderr, "Descriptor data still left\n");
|
---|
558 | else if (res < 0)
|
---|
559 | fprintf(stderr, "Unable to parse descriptors\n");
|
---|
560 | }
|
---|
561 |
|
---|
562 | free(bigbuffer);
|
---|
563 | }
|
---|
564 |
|
---|
565 | return;
|
---|
566 |
|
---|
567 | err:
|
---|
568 | free(dev->config);
|
---|
569 |
|
---|
570 | dev->config = NULL;
|
---|
571 | }
|
---|
572 |
|
---|