Commit c75f57fba4712fed1b0f7b9b10c2bbfdb9ede449

Authored by Stefan Brüns
Committed by Marek Vasut
1 parent 78680314c5

usb: Alloc buffer for USB descriptor dynamically

The configuration descriptor includes all interface, endpoint and
auxiliary descriptors (e.g. report, union) so 512 bytes may not be enough.

Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
Reviewed-by: Marek Vasut <marex@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 2 changed files with 31 additions and 16 deletions Side-by-side Diff

... ... @@ -566,13 +566,12 @@
566 566 }
567 567  
568 568 /**********************************************************************
569   - * gets configuration cfgno and store it in the buffer
  569 + * gets len of configuration cfgno
570 570 */
571   -int usb_get_configuration_no(struct usb_device *dev,
572   - unsigned char *buffer, int cfgno)
  571 +int usb_get_configuration_len(struct usb_device *dev, int cfgno)
573 572 {
574 573 int result;
575   - unsigned int length;
  574 + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 9);
576 575 struct usb_config_descriptor *config;
577 576  
578 577 config = (struct usb_config_descriptor *)&buffer[0];
579 578  
580 579  
581 580  
... ... @@ -586,17 +585,23 @@
586 585 "(expected %i, got %i)\n", 9, result);
587 586 return -EIO;
588 587 }
589   - length = le16_to_cpu(config->wTotalLength);
  588 + return le16_to_cpu(config->wTotalLength);
  589 +}
590 590  
591   - if (length > USB_BUFSIZ) {
592   - printf("%s: failed to get descriptor - too long: %d\n",
593   - __func__, length);
594   - return -EIO;
595   - }
  591 +/**********************************************************************
  592 + * gets configuration cfgno and store it in the buffer
  593 + */
  594 +int usb_get_configuration_no(struct usb_device *dev, int cfgno,
  595 + unsigned char *buffer, int length)
  596 +{
  597 + int result;
  598 + struct usb_config_descriptor *config;
596 599  
  600 + config = (struct usb_config_descriptor *)&buffer[0];
597 601 result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, length);
598   - debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result, length);
599   - config->wTotalLength = length; /* validated, with CPU byte order */
  602 + debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result,
  603 + le16_to_cpu(config->wTotalLength));
  604 + config->wTotalLength = result; /* validated, with CPU byte order */
600 605  
601 606 return result;
602 607 }
... ... @@ -1070,7 +1075,7 @@
1070 1075  
1071 1076 int usb_select_config(struct usb_device *dev)
1072 1077 {
1073   - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);
  1078 + unsigned char *tmpbuf = 0;
1074 1079 int err;
1075 1080  
1076 1081 err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE);
1077 1082  
1078 1083  
... ... @@ -1084,14 +1089,23 @@
1084 1089 le16_to_cpus(&dev->descriptor.bcdDevice);
1085 1090  
1086 1091 /* only support for one config for now */
1087   - err = usb_get_configuration_no(dev, tmpbuf, 0);
  1092 + err = usb_get_configuration_len(dev, 0);
  1093 + if (err >= 0) {
  1094 + tmpbuf = (unsigned char *)malloc_cache_aligned(err);
  1095 + if (!tmpbuf)
  1096 + err = -ENOMEM;
  1097 + else
  1098 + err = usb_get_configuration_no(dev, 0, tmpbuf, err);
  1099 + }
1088 1100 if (err < 0) {
1089 1101 printf("usb_new_device: Cannot read configuration, " \
1090 1102 "skipping device %04x:%04x\n",
1091 1103 dev->descriptor.idVendor, dev->descriptor.idProduct);
  1104 + free(tmpbuf);
1092 1105 return err;
1093 1106 }
1094 1107 usb_parse_config(dev, tmpbuf, 0);
  1108 + free(tmpbuf);
1095 1109 usb_set_maxpacket(dev);
1096 1110 /*
1097 1111 * we set the default configuration here
... ... @@ -266,8 +266,9 @@
266 266 void *buffer, int transfer_len, int interval);
267 267 int usb_disable_asynch(int disable);
268 268 int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
269   -int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer,
270   - int cfgno);
  269 +int usb_get_configuration_no(struct usb_device *dev, int cfgno,
  270 + unsigned char *buffer, int length);
  271 +int usb_get_configuration_len(struct usb_device *dev, int cfgno);
271 272 int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
272 273 unsigned char id, void *buf, int size);
273 274 int usb_get_class_descriptor(struct usb_device *dev, int ifnum,