From 7455af41d19d5e0194e23f3b06f1bf64e3430d62 Mon Sep 17 00:00:00 2001 From: Bartlomiej Sieka Date: Wed, 2 Aug 2006 00:54:18 +0200 Subject: Add rudimentary handling of alternate settings of USB interfaces - to fix problems with some USB storage devices. Some code readability improvements. --- CHANGELOG | 4 +++ common/cmd_usb.c | 2 +- common/usb.c | 86 ++++++++++++++++++++++++++++++++++---------------------- include/usb.h | 1 + 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fb8816472..e9811168a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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. 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; - - 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;ibLength; 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, diff --git a/include/usb.h b/include/usb.h index 39d7f23cc..bf7155404 100644 --- a/include/usb.h +++ b/include/usb.h @@ -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)); -- cgit v1.2.3 From e51aae382979dd838cd5d4027bb21072b7f03a20 Mon Sep 17 00:00:00 2001 From: Bartlomiej Sieka Date: Thu, 3 Aug 2006 23:20:13 +0200 Subject: Prevent USB commands from working when USB is stopped. --- CHANGELOG | 2 ++ common/cmd_usb.c | 5 +++++ common/usb.c | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index e9811168a..df1b6d0b1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,8 @@ Changes since U-Boot 1.1.4: ====================================================================== +* Prevent USB commands from working when USB is stopped. + * 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. diff --git a/common/cmd_usb.c b/common/cmd_usb.c index fcc66621a..28c05aa20 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -444,6 +444,7 @@ int do_usb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int i; struct usb_device *dev = NULL; + extern char usb_started; #ifdef CONFIG_USB_STORAGE block_dev_desc_t *stor_dev; #endif @@ -477,6 +478,10 @@ int do_usb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) usb_stop(); return 0; } + if (!usb_started) { + printf("USB is stopped. Please issue 'usb start' first.\n"); + return 1; + } if (strncmp(argv[1],"tree",4) == 0) { printf("\nDevice Tree:\n"); usb_show_tree(usb_get_dev_index(0)); diff --git a/common/usb.c b/common/usb.c index b1b7aec62..0857494b2 100644 --- a/common/usb.c +++ b/common/usb.c @@ -72,6 +72,8 @@ static int running; static int asynch_allowed; static struct devrequest setup_packet; +char usb_started; /* flag for the started/stopped USB status */ + /********************************************************************** * some forward declerations... */ @@ -110,10 +112,12 @@ int usb_init(void) printf("scanning bus for devices... "); running=1; usb_scan_devices(); + usb_started = 1; return 0; } else { printf("Error, couldn't init Lowlevel part\n"); + usb_started = 0; return -1; } } @@ -124,6 +128,7 @@ int usb_init(void) int usb_stop(void) { asynch_allowed=1; + usb_started = 0; usb_hub_reset(); return usb_lowlevel_stop(); } -- cgit v1.2.3