From c75f57fba4712fed1b0f7b9b10c2bbfdb9ede449 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stefan=20Br=C3=BCns?= Date: Tue, 22 Dec 2015 01:18:13 +0100 Subject: [PATCH] usb: Alloc buffer for USB descriptor dynamically MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Marek Vasut Reviewed-by: Simon Glass --- common/usb.c | 42 ++++++++++++++++++++++++++++-------------- include/usb.h | 5 +++-- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/common/usb.c b/common/usb.c index 700bfc315b..b1773914cf 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 55b9268ea1..198ecbcbe3 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, -- 2.39.5