Commit 7455af41 authored by Bartlomiej Sieka's avatar Bartlomiej Sieka
Browse files

Add rudimentary handling of alternate settings of USB interfaces - to fix

problems with some USB storage devices. Some code readability improvements.
parent f3e06df7
......@@ -2,6 +2,10 @@
Changes since U-Boot 1.1.4:
======================================================================
* Add rudimentary handling of alternate settings of USB interfaces.
This is in order to fix issues with some USB sticks or knives timing
out during initialisation. Some code readability improvements.
* Enable buffered flash writes for TQM5200 board.
* Fix problems with SanDisk Corporation Cruzer Micro USB memory stick.
......
......@@ -186,7 +186,7 @@ void usb_display_conf_desc(struct usb_config_descriptor *config,struct usb_devic
void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,struct usb_device *dev)
{
printf(" Interface: %d\n",ifdesc->bInterfaceNumber);
printf(" - Alternate Settings %d, Endpoints: %d\n",ifdesc->bAlternateSetting,ifdesc->bNumEndpoints);
printf(" - Alternate Setting %d, Endpoints: %d\n",ifdesc->bAlternateSetting,ifdesc->bNumEndpoints);
printf(" - Class ");
usb_display_class_sub(ifdesc->bInterfaceClass,ifdesc->bInterfaceSubClass,ifdesc->bInterfaceProtocol);
printf("\n");
......
......@@ -280,56 +280,68 @@ int usb_set_maxpacket(struct usb_device *dev)
int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
{
struct usb_descriptor_header *head;
int index,ifno,epno;
ifno=-1;
epno=-1;
dev->configno=cfgno;
head =(struct usb_descriptor_header *)&buffer[0];
if(head->bDescriptorType!=USB_DT_CONFIG) {
printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType);
int index, ifno, epno, curr_if_num;
int i;
unsigned char *ch;
ifno = -1;
epno = -1;
curr_if_num = -1;
dev->configno = cfgno;
head = (struct usb_descriptor_header *) &buffer[0];
if(head->bDescriptorType != USB_DT_CONFIG) {
printf(" ERROR: NOT USB_CONFIG_DESC %x\n", head->bDescriptorType);
return -1;
}
memcpy(&dev->config,buffer,buffer[0]);
dev->config.wTotalLength=swap_16(dev->config.wTotalLength);
dev->config.no_of_if=0;
memcpy(&dev->config, buffer, buffer[0]);
dev->config.wTotalLength = swap_16(dev->config.wTotalLength);
dev->config.no_of_if = 0;
index=dev->config.bLength;
index = dev->config.bLength;
/* Ok the first entry must be a configuration entry, now process the others */
head=(struct usb_descriptor_header *)&buffer[index];
while(index+1 < dev->config.wTotalLength) {
head = (struct usb_descriptor_header *) &buffer[index];
while(index + 1 < dev->config.wTotalLength) {
switch(head->bDescriptorType) {
case USB_DT_INTERFACE:
ifno=dev->config.no_of_if;
dev->config.no_of_if++; /* found an interface desc, increase numbers */
memcpy(&dev->config.if_desc[ifno],&buffer[index],buffer[index]); /* copy new desc */
dev->config.if_desc[ifno].no_of_ep=0;
if(((struct usb_interface_descriptor *) &buffer[index])->
bInterfaceNumber != curr_if_num) {
/* this is a new interface, copy new desc */
ifno = dev->config.no_of_if;
dev->config.no_of_if++;
memcpy(&dev->config.if_desc[ifno],
&buffer[index], buffer[index]);
dev->config.if_desc[ifno].no_of_ep = 0;
dev->config.if_desc[ifno].num_altsetting = 1;
curr_if_num = dev->config.if_desc[ifno].bInterfaceNumber;
} else {
/* found alternate setting for the interface */
dev->config.if_desc[ifno].num_altsetting++;
}
break;
case USB_DT_ENDPOINT:
epno=dev->config.if_desc[ifno].no_of_ep;
epno = dev->config.if_desc[ifno].no_of_ep;
dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */
memcpy(&dev->config.if_desc[ifno].ep_desc[epno],&buffer[index],buffer[index]);
dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize
=swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize);
USB_PRINTF("if %d, ep %d\n",ifno,epno);
memcpy(&dev->config.if_desc[ifno].ep_desc[epno],
&buffer[index], buffer[index]);
dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize =
swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize);
USB_PRINTF("if %d, ep %d\n", ifno, epno);
break;
default:
if(head->bLength==0)
if(head->bLength == 0)
return 1;
USB_PRINTF("unknown Description Type : %x\n",head->bDescriptorType);
USB_PRINTF("unknown Description Type : %x\n", head->bDescriptorType);
{
int i;
unsigned char *ch;
ch=(unsigned char *)head;
for(i=0;i<head->bLength; i++)
USB_PRINTF("%02X ",*ch++);
ch = (unsigned char *)head;
for(i = 0; i < head->bLength; i++)
USB_PRINTF("%02X ", *ch++);
USB_PRINTF("\n\n\n");
}
break;
}
index+=head->bLength;
head=(struct usb_descriptor_header *)&buffer[index];
index += head->bLength;
head = (struct usb_descriptor_header *)&buffer[index];
}
return 1;
}
......@@ -443,6 +455,14 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
printf("selecting invalid interface %d", interface);
return -1;
}
/*
* We should return now for devices with only one alternate setting.
* According to 9.4.10 of the Universal Serial Bus Specification Revision 2.0
* such devices can return with a STALL. This results in some USB sticks
* timeouting during initialization and then being unusable in U-Boot.
*/
if (if_face->num_altsetting == 1)
return 0;
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
......
......@@ -108,6 +108,7 @@ struct usb_interface_descriptor {
unsigned char iInterface;
unsigned char no_of_ep;
unsigned char num_altsetting;
unsigned char act_altsetting;
struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
} __attribute__ ((packed));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment