[175] | 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 |
|
---|