Commit c75f57fba4712fed1b0f7b9b10c2bbfdb9ede449
Committed by
Marek Vasut
1 parent
78680314c5
Exists in
v2017.01-smarct4x
and in
30 other branches
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
common/usb.c
... | ... | @@ -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 |
include/usb.h
... | ... | @@ -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, |