summaryrefslogtreecommitdiff
path: root/common/usb.c
diff options
context:
space:
mode:
authorStefan Brüns <stefan.bruens@rwth-aachen.de>2015-12-22 01:18:13 +0100
committerMarek Vasut <marex@denx.de>2015-12-31 10:05:31 +0100
commitc75f57fba4712fed1b0f7b9b10c2bbfdb9ede449 (patch)
tree0266dc3aca10dca86b9881543edc738718105963 /common/usb.c
parent78680314c53a95c0bb25e942662979843b60d7b9 (diff)
downloadu-boot-c75f57fba4712fed1b0f7b9b10c2bbfdb9ede449.tar.gz
u-boot-c75f57fba4712fed1b0f7b9b10c2bbfdb9ede449.tar.bz2
u-boot-c75f57fba4712fed1b0f7b9b10c2bbfdb9ede449.zip
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>
Diffstat (limited to 'common/usb.c')
-rw-r--r--common/usb.c42
1 files changed, 28 insertions, 14 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