diff options
author | Stefan Brüns | 2015-12-22 01:18:13 +0100 |
---|---|---|
committer | Marek Vasut | 2015-12-31 10:05:31 +0100 |
commit | c75f57fba4712fed1b0f7b9b10c2bbfdb9ede449 (patch) | |
tree | 0266dc3aca10dca86b9881543edc738718105963 | |
parent | 78680314c53a95c0bb25e942662979843b60d7b9 (diff) |
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>
-rw-r--r-- | common/usb.c | 42 | ||||
-rw-r--r-- | include/usb.h | 5 |
2 files changed, 31 insertions, 16 deletions
diff --git a/common/usb.c b/common/usb.c index 700bfc315b6..b1773914cf0 100644 --- a/common/usb.c +++ b/common/usb.c @@ -566,13 +566,12 @@ static int usb_get_descriptor(struct usb_device *dev, unsigned char type, } /********************************************************************** - * gets configuration cfgno and store it in the buffer + * gets len of configuration cfgno */ -int usb_get_configuration_no(struct usb_device *dev, - unsigned char *buffer, int cfgno) +int usb_get_configuration_len(struct usb_device *dev, int cfgno) { int result; - unsigned int length; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 9); struct usb_config_descriptor *config; config = (struct usb_config_descriptor *)&buffer[0]; @@ -586,17 +585,23 @@ int usb_get_configuration_no(struct usb_device *dev, "(expected %i, got %i)\n", 9, result); return -EIO; } - length = le16_to_cpu(config->wTotalLength); + return le16_to_cpu(config->wTotalLength); +} - if (length > USB_BUFSIZ) { - printf("%s: failed to get descriptor - too long: %d\n", - __func__, length); - return -EIO; - } +/********************************************************************** + * gets configuration cfgno and store it in the buffer + */ +int usb_get_configuration_no(struct usb_device *dev, int cfgno, + unsigned char *buffer, int length) +{ + int result; + struct usb_config_descriptor *config; + config = (struct usb_config_descriptor *)&buffer[0]; result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, length); - debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result, length); - config->wTotalLength = length; /* validated, with CPU byte order */ + debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result, + le16_to_cpu(config->wTotalLength)); + config->wTotalLength = result; /* validated, with CPU byte order */ return result; } @@ -1070,7 +1075,7 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, int usb_select_config(struct usb_device *dev) { - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + unsigned char *tmpbuf = 0; int err; err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE); @@ -1084,14 +1089,23 @@ int usb_select_config(struct usb_device *dev) le16_to_cpus(&dev->descriptor.bcdDevice); /* only support for one config for now */ - err = usb_get_configuration_no(dev, tmpbuf, 0); + err = usb_get_configuration_len(dev, 0); + if (err >= 0) { + tmpbuf = (unsigned char *)malloc_cache_aligned(err); + if (!tmpbuf) + err = -ENOMEM; + else + err = usb_get_configuration_no(dev, 0, tmpbuf, err); + } if (err < 0) { printf("usb_new_device: Cannot read configuration, " \ "skipping device %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); + free(tmpbuf); return err; } usb_parse_config(dev, tmpbuf, 0); + free(tmpbuf); usb_set_maxpacket(dev); /* * we set the default configuration here diff --git a/include/usb.h b/include/usb.h index 55b9268ea16..198ecbcbe32 100644 --- a/include/usb.h +++ b/include/usb.h @@ -266,8 +266,9 @@ int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval); int usb_disable_asynch(int disable); int usb_maxpacket(struct usb_device *dev, unsigned long pipe); -int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer, - int cfgno); +int usb_get_configuration_no(struct usb_device *dev, int cfgno, + unsigned char *buffer, int length); +int usb_get_configuration_len(struct usb_device *dev, int cfgno); int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size); int usb_get_class_descriptor(struct usb_device *dev, int ifnum, |