mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-14 17:07:38 +00:00
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>
This commit is contained in:
parent
78680314c5
commit
c75f57fba4
2 changed files with 31 additions and 16 deletions
42
common/usb.c
42
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,
|
int usb_get_configuration_len(struct usb_device *dev, int cfgno)
|
||||||
unsigned char *buffer, int cfgno)
|
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
unsigned int length;
|
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 9);
|
||||||
struct usb_config_descriptor *config;
|
struct usb_config_descriptor *config;
|
||||||
|
|
||||||
config = (struct usb_config_descriptor *)&buffer[0];
|
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);
|
"(expected %i, got %i)\n", 9, result);
|
||||||
return -EIO;
|
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",
|
* gets configuration cfgno and store it in the buffer
|
||||||
__func__, length);
|
*/
|
||||||
return -EIO;
|
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);
|
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, length);
|
||||||
debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result, length);
|
debug("get_conf_no %d Result %d, wLength %d\n", cfgno, result,
|
||||||
config->wTotalLength = length; /* validated, with CPU byte order */
|
le16_to_cpu(config->wTotalLength));
|
||||||
|
config->wTotalLength = result; /* validated, with CPU byte order */
|
||||||
|
|
||||||
return result;
|
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)
|
int usb_select_config(struct usb_device *dev)
|
||||||
{
|
{
|
||||||
ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);
|
unsigned char *tmpbuf = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE);
|
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);
|
le16_to_cpus(&dev->descriptor.bcdDevice);
|
||||||
|
|
||||||
/* only support for one config for now */
|
/* 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) {
|
if (err < 0) {
|
||||||
printf("usb_new_device: Cannot read configuration, " \
|
printf("usb_new_device: Cannot read configuration, " \
|
||||||
"skipping device %04x:%04x\n",
|
"skipping device %04x:%04x\n",
|
||||||
dev->descriptor.idVendor, dev->descriptor.idProduct);
|
dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||||
|
free(tmpbuf);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
usb_parse_config(dev, tmpbuf, 0);
|
usb_parse_config(dev, tmpbuf, 0);
|
||||||
|
free(tmpbuf);
|
||||||
usb_set_maxpacket(dev);
|
usb_set_maxpacket(dev);
|
||||||
/*
|
/*
|
||||||
* we set the default configuration here
|
* we set the default configuration here
|
||||||
|
|
|
@ -266,8 +266,9 @@ int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
|
||||||
void *buffer, int transfer_len, int interval);
|
void *buffer, int transfer_len, int interval);
|
||||||
int usb_disable_asynch(int disable);
|
int usb_disable_asynch(int disable);
|
||||||
int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
|
int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
|
||||||
int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer,
|
int usb_get_configuration_no(struct usb_device *dev, int cfgno,
|
||||||
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,
|
int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
|
||||||
unsigned char id, void *buf, int size);
|
unsigned char id, void *buf, int size);
|
||||||
int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
|
int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
|
||||||
|
|
Loading…
Reference in a new issue