diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/cmd_usb.c | 2 | ||||
| -rw-r--r-- | common/usb.c | 84 | 
2 files changed, 53 insertions, 33 deletions
| diff --git a/common/cmd_usb.c b/common/cmd_usb.c index fdfd042ac..fcc66621a 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -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"); diff --git a/common/usb.c b/common/usb.c index d9515e659..b1b7aec62 100644 --- a/common/usb.c +++ b/common/usb.c @@ -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; +	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); +	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, |