Refactoring parts of the common USB OHCI code

This patch refactors some large routines of the USB OHCI code by
making some routines smaller and more readable which helps
debugging and understanding the code. (Makes the code looks
somewhat more like the Linux implementation.)

Also made entire file compliant to Linux Coding Rules (checkpatch.pl compliant)

Signed-off-by: Remy Bohmer <linux@bohmer.net>
Signed-off-by: Markus Klotzbuecher <mk@denx.de>
This commit is contained in:
Remy Bohmer 2008-09-16 14:55:43 +02:00 committed by Markus Klotzbuecher
parent be19d324ed
commit 6f5794a6f7
3 changed files with 866 additions and 691 deletions

View File

@ -58,9 +58,9 @@
#undef USB_DEBUG #undef USB_DEBUG
#ifdef USB_DEBUG #ifdef USB_DEBUG
#define USB_PRINTF(fmt,args...) printf (fmt ,##args) #define USB_PRINTF(fmt, args...) printf (fmt , ##args)
#else #else
#define USB_PRINTF(fmt,args...) #define USB_PRINTF(fmt, args...)
#endif #endif
#define USB_BUFSIZ 512 #define USB_BUFSIZ 512
@ -88,7 +88,7 @@ void usb_hub_reset(void);
void __inline__ wait_ms(unsigned long ms) void __inline__ wait_ms(unsigned long ms)
{ {
while(ms-->0) while (ms-- > 0)
udelay(1000); udelay(1000);
} }
/*************************************************************************** /***************************************************************************
@ -99,22 +99,22 @@ int usb_init(void)
{ {
int result; int result;
running=0; running = 0;
dev_index=0; dev_index = 0;
asynch_allowed=1; asynch_allowed = 1;
usb_hub_reset(); usb_hub_reset();
/* init low_level USB */ /* init low_level USB */
printf("USB: "); printf("USB: ");
result = usb_lowlevel_init(); result = usb_lowlevel_init();
/* if lowlevel init is OK, scan the bus for devices i.e. search HUBs and configure them */ /* if lowlevel init is OK, scan the bus for devices
if(result==0) { * i.e. search HUBs and configure them */
if (result == 0) {
printf("scanning bus for devices... "); printf("scanning bus for devices... ");
running=1; running = 1;
usb_scan_devices(); usb_scan_devices();
usb_started = 1; usb_started = 1;
return 0; return 0;
} } else {
else {
printf("Error, couldn't init Lowlevel part\n"); printf("Error, couldn't init Lowlevel part\n");
usb_started = 0; usb_started = 0;
return -1; return -1;
@ -143,7 +143,7 @@ int usb_stop(void)
*/ */
void usb_disable_asynch(int disable) void usb_disable_asynch(int disable)
{ {
asynch_allowed=!disable; asynch_allowed = !disable;
} }
@ -156,9 +156,9 @@ void usb_disable_asynch(int disable)
* submits an Interrupt Message * submits an Interrupt Message
*/ */
int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, 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)
{ {
return submit_int_msg(dev,pipe,buffer,transfer_len,interval); return submit_int_msg(dev, pipe, buffer, transfer_len, interval);
} }
/* /*
@ -175,8 +175,10 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
unsigned short value, unsigned short index, unsigned short value, unsigned short index,
void *data, unsigned short size, int timeout) void *data, unsigned short size, int timeout)
{ {
if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */ if ((timeout == 0) && (!asynch_allowed)) {
/* request for a asynch control pipe is not allowed */
return -1; return -1;
}
/* set setup command */ /* set setup command */
setup_packet.requesttype = requesttype; setup_packet.requesttype = requesttype;
@ -184,24 +186,24 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
setup_packet.value = cpu_to_le16(value); setup_packet.value = cpu_to_le16(value);
setup_packet.index = cpu_to_le16(index); setup_packet.index = cpu_to_le16(index);
setup_packet.length = cpu_to_le16(size); setup_packet.length = cpu_to_le16(size);
USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X, value 0x%X index 0x%X length 0x%X\n", USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X, " \
request,requesttype,value,index,size); "value 0x%X index 0x%X length 0x%X\n",
dev->status=USB_ST_NOT_PROC; /*not yet processed */ request, requesttype, value, index, size);
dev->status = USB_ST_NOT_PROC; /*not yet processed */
submit_control_msg(dev,pipe,data,size,&setup_packet); submit_control_msg(dev, pipe, data, size, &setup_packet);
if(timeout==0) { if (timeout == 0)
return (int)size; return (int)size;
}
while(timeout--) { while (timeout--) {
if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
break; break;
wait_ms(1); wait_ms(1);
} }
if(dev->status==0) if (dev->status == 0)
return dev->act_len; return dev->act_len;
else { else
return -1; return -1;
}
} }
/*------------------------------------------------------------------- /*-------------------------------------------------------------------
@ -214,15 +216,15 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
{ {
if (len < 0) if (len < 0)
return -1; return -1;
dev->status=USB_ST_NOT_PROC; /*not yet processed */ dev->status = USB_ST_NOT_PROC; /*not yet processed */
submit_bulk_msg(dev,pipe,data,len); submit_bulk_msg(dev, pipe, data, len);
while(timeout--) { while (timeout--) {
if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC)) if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
break; break;
wait_ms(1); wait_ms(1);
} }
*actual_length=dev->act_len; *actual_length = dev->act_len;
if(dev->status==0) if (dev->status == 0)
return 0; return 0;
else else
return -1; return -1;
@ -237,9 +239,10 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
* returns the max packet size, depending on the pipe direction and * returns the max packet size, depending on the pipe direction and
* the configurations values * the configurations values
*/ */
int usb_maxpacket(struct usb_device *dev,unsigned long pipe) int usb_maxpacket(struct usb_device *dev, unsigned long pipe)
{ {
if((pipe & USB_DIR_IN)==0) /* direction is out -> use emaxpacket out */ /* direction is out -> use emaxpacket out */
if ((pipe & USB_DIR_IN) == 0)
return(dev->epmaxpacketout[((pipe>>15) & 0xf)]); return(dev->epmaxpacketout[((pipe>>15) & 0xf)]);
else else
return(dev->epmaxpacketin[((pipe>>15) & 0xf)]); return(dev->epmaxpacketin[((pipe>>15) & 0xf)]);
@ -318,8 +321,9 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
dev->configno = cfgno; dev->configno = cfgno;
head = (struct usb_descriptor_header *) &buffer[0]; head = (struct usb_descriptor_header *) &buffer[0];
if(head->bDescriptorType != USB_DT_CONFIG) { if (head->bDescriptorType != USB_DT_CONFIG) {
printf(" ERROR: NOT USB_CONFIG_DESC %x\n", head->bDescriptorType); printf(" ERROR: NOT USB_CONFIG_DESC %x\n",
head->bDescriptorType);
return -1; return -1;
} }
memcpy(&dev->config, buffer, buffer[0]); memcpy(&dev->config, buffer, buffer[0]);
@ -327,45 +331,52 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
dev->config.no_of_if = 0; 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 */ /* Ok the first entry must be a configuration entry,
* now process the others */
head = (struct usb_descriptor_header *) &buffer[index]; head = (struct usb_descriptor_header *) &buffer[index];
while(index + 1 < dev->config.wTotalLength) { while (index + 1 < dev->config.wTotalLength) {
switch(head->bDescriptorType) { switch (head->bDescriptorType) {
case USB_DT_INTERFACE: case USB_DT_INTERFACE:
if(((struct usb_interface_descriptor *) &buffer[index])-> if (((struct usb_interface_descriptor *) \
bInterfaceNumber != curr_if_num) { &buffer[index])->bInterfaceNumber != curr_if_num) {
/* this is a new interface, copy new desc */ /* this is a new interface, copy new desc */
ifno = dev->config.no_of_if; ifno = dev->config.no_of_if;
dev->config.no_of_if++; dev->config.no_of_if++;
memcpy(&dev->config.if_desc[ifno], 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;
dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */
memcpy(&dev->config.if_desc[ifno].ep_desc[epno],
&buffer[index], buffer[index]); &buffer[index], buffer[index]);
le16_to_cpus(&(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize)); dev->config.if_desc[ifno].no_of_ep = 0;
USB_PRINTF("if %d, ep %d\n", ifno, epno); dev->config.if_desc[ifno].num_altsetting = 1;
break; curr_if_num =
default: dev->config.if_desc[ifno].bInterfaceNumber;
if(head->bLength == 0) } else {
return 1; /* found alternate setting for the interface */
USB_PRINTF("unknown Description Type : %x\n", head->bDescriptorType); dev->config.if_desc[ifno].num_altsetting++;
{ }
ch = (unsigned char *)head; break;
for(i = 0; i < head->bLength; i++) case USB_DT_ENDPOINT:
USB_PRINTF("%02X ", *ch++); epno = dev->config.if_desc[ifno].no_of_ep;
USB_PRINTF("\n\n\n"); /* found an endpoint */
} dev->config.if_desc[ifno].no_of_ep++;
break; memcpy(&dev->config.if_desc[ifno].ep_desc[epno],
&buffer[index], buffer[index]);
le16_to_cpus(&(dev->config.if_desc[ifno].ep_desc[epno].\
wMaxPacketSize));
USB_PRINTF("if %d, ep %d\n", ifno, epno);
break;
default:
if (head->bLength == 0)
return 1;
USB_PRINTF("unknown Description Type : %x\n",
head->bDescriptorType);
{
ch = (unsigned char *)head;
for (i = 0; i < head->bLength; i++)
USB_PRINTF("%02X ", *ch++);
USB_PRINTF("\n\n\n");
}
break;
} }
index += head->bLength; index += head->bLength;
head = (struct usb_descriptor_header *)&buffer[index]; head = (struct usb_descriptor_header *)&buffer[index];
@ -384,7 +395,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7); int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3); USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
/* don't clear if failed */ /* don't clear if failed */
if (result < 0) if (result < 0)
@ -406,7 +418,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
/********************************************************************** /**********************************************************************
* get_descriptor type * get_descriptor type
*/ */
int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) int usb_get_descriptor(struct usb_device *dev, unsigned char type,
unsigned char index, void *buf, int size)
{ {
int res; int res;
res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
@ -419,32 +432,36 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
/********************************************************************** /**********************************************************************
* gets configuration cfgno and store it in the buffer * gets configuration cfgno and store it in the buffer
*/ */
int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno) int usb_get_configuration_no(struct usb_device *dev,
unsigned char *buffer, int cfgno)
{ {
int result; int result;
unsigned int tmp; unsigned int tmp;
struct usb_config_descriptor *config; struct usb_config_descriptor *config;
config=(struct usb_config_descriptor *)&buffer[0]; config = (struct usb_config_descriptor *)&buffer[0];
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
if (result < 8) { if (result < 8) {
if (result < 0) if (result < 0)
printf("unable to get descriptor, error %lX\n",dev->status); printf("unable to get descriptor, error %lX\n",
dev->status);
else else
printf("config descriptor too short (expected %i, got %i)\n",8,result); printf("config descriptor too short " \
"(expected %i, got %i)\n", 8, result);
return -1; return -1;
} }
tmp = le16_to_cpu(config->wTotalLength); tmp = le16_to_cpu(config->wTotalLength);
if (tmp > USB_BUFSIZ) { if (tmp > USB_BUFSIZ) {
USB_PRINTF("usb_get_configuration_no: failed to get descriptor - too long: %d\n", USB_PRINTF("usb_get_configuration_no: failed to get " \
tmp); "descriptor - too long: %d\n", tmp);
return -1; return -1;
} }
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp); result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp);
USB_PRINTF("get_conf_no %d Result %d, wLength %d\n",cfgno,result,tmp); USB_PRINTF("get_conf_no %d Result %d, wLength %d\n",
cfgno, result, tmp);
return result; return result;
} }
@ -456,11 +473,11 @@ int usb_set_address(struct usb_device *dev)
{ {
int res; int res;
USB_PRINTF("set address %d\n",dev->devnum); USB_PRINTF("set address %d\n", dev->devnum);
res=usb_control_msg(dev, usb_snddefctrl(dev), res = usb_control_msg(dev, usb_snddefctrl(dev),
USB_REQ_SET_ADDRESS, 0, USB_REQ_SET_ADDRESS, 0,
(dev->devnum),0, (dev->devnum), 0,
NULL,0, USB_CNTL_TIMEOUT); NULL, 0, USB_CNTL_TIMEOUT);
return res; return res;
} }
@ -484,16 +501,19 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
} }
/* /*
* We should return now for devices with only one alternate setting. * 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 * According to 9.4.10 of the Universal Serial Bus Specification
* such devices can return with a STALL. This results in some USB sticks * Revision 2.0 such devices can return with a STALL. This results in
* timeouting during initialization and then being unusable in U-Boot. * some USB sticks timeouting during initialization and then being
* unusable in U-Boot.
*/ */
if (if_face->num_altsetting == 1) if (if_face->num_altsetting == 1)
return 0; return 0;
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
interface, NULL, 0, USB_CNTL_TIMEOUT * 5)) < 0) alternate, interface, NULL, 0,
USB_CNTL_TIMEOUT * 5);
if (ret < 0)
return ret; return ret;
return 0; return 0;
@ -505,18 +525,17 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
int usb_set_configuration(struct usb_device *dev, int configuration) int usb_set_configuration(struct usb_device *dev, int configuration)
{ {
int res; int res;
USB_PRINTF("set configuration %d\n",configuration); USB_PRINTF("set configuration %d\n", configuration);
/* set setup command */ /* set setup command */
res=usb_control_msg(dev, usb_sndctrlpipe(dev,0), res = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0, USB_REQ_SET_CONFIGURATION, 0,
configuration,0, configuration, 0,
NULL,0, USB_CNTL_TIMEOUT); NULL, 0, USB_CNTL_TIMEOUT);
if(res==0) { if (res == 0) {
dev->toggle[0] = 0; dev->toggle[0] = 0;
dev->toggle[1] = 0; dev->toggle[1] = 0;
return 0; return 0;
} } else
else
return -1; return -1;
} }
@ -543,11 +562,13 @@ int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
/******************************************************************** /********************************************************************
* get report * get report
*/ */
int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size) int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
unsigned char id, void *buf, int size)
{ {
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_REQ_GET_REPORT,
(type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
(type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
} }
/******************************************************************** /********************************************************************
@ -564,7 +585,8 @@ int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
/******************************************************************** /********************************************************************
* get string index in buffer * get string index in buffer
*/ */
int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) int usb_get_string(struct usb_device *dev, unsigned short langid,
unsigned char index, void *buf, int size)
{ {
int i; int i;
int result; int result;
@ -655,17 +677,19 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
if (!dev->have_langid) { if (!dev->have_langid) {
err = usb_string_sub(dev, 0, 0, tbuf); err = usb_string_sub(dev, 0, 0, tbuf);
if (err < 0) { if (err < 0) {
USB_PRINTF("error getting string descriptor 0 (error=%x)\n",dev->status); USB_PRINTF("error getting string descriptor 0 " \
"(error=%x)\n", dev->status);
return -1; return -1;
} else if (tbuf[0] < 4) { } else if (tbuf[0] < 4) {
USB_PRINTF("string descriptor 0 too short\n"); USB_PRINTF("string descriptor 0 too short\n");
return -1; return -1;
} else { } else {
dev->have_langid = -1; dev->have_langid = -1;
dev->string_langid = tbuf[2] | (tbuf[3]<< 8); dev->string_langid = tbuf[2] | (tbuf[3] << 8);
/* always use the first langid listed */ /* always use the first langid listed */
USB_PRINTF("USB device number %d default language ID 0x%x\n", USB_PRINTF("USB device number %d default " \
dev->devnum, dev->string_langid); "language ID 0x%x\n",
dev->devnum, dev->string_langid);
} }
} }
@ -697,9 +721,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
/* returns a pointer to the device with the index [index]. /* returns a pointer to the device with the index [index].
* if the device is not assigned (dev->devnum==-1) returns NULL * if the device is not assigned (dev->devnum==-1) returns NULL
*/ */
struct usb_device * usb_get_dev_index(int index) struct usb_device *usb_get_dev_index(int index)
{ {
if(usb_dev[index].devnum==-1) if (usb_dev[index].devnum == -1)
return NULL; return NULL;
else else
return &usb_dev[index]; return &usb_dev[index];
@ -709,21 +733,22 @@ struct usb_device * usb_get_dev_index(int index)
/* returns a pointer of a new device structure or NULL, if /* returns a pointer of a new device structure or NULL, if
* no device struct is available * no device struct is available
*/ */
struct usb_device * usb_alloc_new_device(void) struct usb_device *usb_alloc_new_device(void)
{ {
int i; int i;
USB_PRINTF("New Device %d\n",dev_index); USB_PRINTF("New Device %d\n", dev_index);
if(dev_index==USB_MAX_DEVICE) { if (dev_index == USB_MAX_DEVICE) {
printf("ERROR, too many USB Devices, max=%d\n",USB_MAX_DEVICE); printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE);
return NULL; return NULL;
} }
usb_dev[dev_index].devnum=dev_index+1; /* default Address is 0, real addresses start with 1 */ /* default Address is 0, real addresses start with 1 */
usb_dev[dev_index].maxchild=0; usb_dev[dev_index].devnum = dev_index + 1;
for(i=0;i<USB_MAXCHILDREN;i++) usb_dev[dev_index].maxchild = 0;
usb_dev[dev_index].children[i]=NULL; for (i = 0; i < USB_MAXCHILDREN; i++)
usb_dev[dev_index].parent=NULL; usb_dev[dev_index].children[i] = NULL;
usb_dev[dev_index].parent = NULL;
dev_index++; dev_index++;
return &usb_dev[dev_index-1]; return &usb_dev[dev_index - 1];
} }
@ -788,7 +813,7 @@ int usb_new_device(struct usb_device *dev)
} }
} }
if (port < 0) { if (port < 0) {
printf("usb_new_device: cannot locate device's port..\n"); printf("usb_new_device:cannot locate device's port.\n");
return 1; return 1;
} }
@ -803,7 +828,8 @@ int usb_new_device(struct usb_device *dev)
/* and this is the old and known way of initializing devices */ /* and this is the old and known way of initializing devices */
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
if (err < 8) { if (err < 8) {
printf("\n USB device not responding, giving up (status=%lX)\n",dev->status); printf("\n USB device not responding, " \
"giving up (status=%lX)\n", dev->status);
return 1; return 1;
} }
#endif #endif
@ -811,17 +837,18 @@ int usb_new_device(struct usb_device *dev)
dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
switch (dev->descriptor.bMaxPacketSize0) { switch (dev->descriptor.bMaxPacketSize0) {
case 8: dev->maxpacketsize = 0; break; case 8: dev->maxpacketsize = 0; break;
case 16: dev->maxpacketsize = 1; break; case 16: dev->maxpacketsize = 1; break;
case 32: dev->maxpacketsize = 2; break; case 32: dev->maxpacketsize = 2; break;
case 64: dev->maxpacketsize = 3; break; case 64: dev->maxpacketsize = 3; break;
} }
dev->devnum = addr; dev->devnum = addr;
err = usb_set_address(dev); /* set address */ err = usb_set_address(dev); /* set address */
if (err < 0) { if (err < 0) {
printf("\n USB device not accepting new address (error=%lX)\n", dev->status); printf("\n USB device not accepting new address " \
"(error=%lX)\n", dev->status);
return 1; return 1;
} }
@ -829,12 +856,15 @@ int usb_new_device(struct usb_device *dev)
tmp = sizeof(dev->descriptor); tmp = sizeof(dev->descriptor);
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
if (err < tmp) { if (err < tmp) {
if (err < 0) if (err < 0)
printf("unable to get device descriptor (error=%d)\n",err); printf("unable to get device descriptor (error=%d)\n",
err);
else else
printf("USB device descriptor short read (expected %i, got %i)\n",tmp,err); printf("USB device descriptor short read " \
"(expected %i, got %i)\n", tmp, err);
return 1; return 1;
} }
/* correct le values */ /* correct le values */
@ -843,30 +873,35 @@ int usb_new_device(struct usb_device *dev)
le16_to_cpus(&dev->descriptor.idProduct); le16_to_cpus(&dev->descriptor.idProduct);
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 */
usb_get_configuration_no(dev,&tmpbuf[0],0); usb_get_configuration_no(dev, &tmpbuf[0], 0);
usb_parse_config(dev,&tmpbuf[0],0); usb_parse_config(dev, &tmpbuf[0], 0);
usb_set_maxpacket(dev); usb_set_maxpacket(dev);
/* we set the default configuration here */ /* we set the default configuration here */
if (usb_set_configuration(dev, dev->config.bConfigurationValue)) { if (usb_set_configuration(dev, dev->config.bConfigurationValue)) {
printf("failed to set default configuration len %d, status %lX\n",dev->act_len,dev->status); printf("failed to set default configuration " \
"len %d, status %lX\n", dev->act_len, dev->status);
return -1; return -1;
} }
USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); dev->descriptor.iManufacturer, dev->descriptor.iProduct,
dev->descriptor.iSerialNumber);
memset(dev->mf, 0, sizeof(dev->mf)); memset(dev->mf, 0, sizeof(dev->mf));
memset(dev->prod, 0, sizeof(dev->prod)); memset(dev->prod, 0, sizeof(dev->prod));
memset(dev->serial, 0, sizeof(dev->serial)); memset(dev->serial, 0, sizeof(dev->serial));
if (dev->descriptor.iManufacturer) if (dev->descriptor.iManufacturer)
usb_string(dev, dev->descriptor.iManufacturer, dev->mf, sizeof(dev->mf)); usb_string(dev, dev->descriptor.iManufacturer,
dev->mf, sizeof(dev->mf));
if (dev->descriptor.iProduct) if (dev->descriptor.iProduct)
usb_string(dev, dev->descriptor.iProduct, dev->prod, sizeof(dev->prod)); usb_string(dev, dev->descriptor.iProduct,
dev->prod, sizeof(dev->prod));
if (dev->descriptor.iSerialNumber) if (dev->descriptor.iSerialNumber)
usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial)); usb_string(dev, dev->descriptor.iSerialNumber,
dev->serial, sizeof(dev->serial));
USB_PRINTF("Manufacturer %s\n", dev->mf); USB_PRINTF("Manufacturer %s\n", dev->mf);
USB_PRINTF("Product %s\n", dev->prod); USB_PRINTF("Product %s\n", dev->prod);
USB_PRINTF("SerialNumber %s\n", dev->serial); USB_PRINTF("SerialNumber %s\n", dev->serial);
/* now prode if the device is a hub */ /* now prode if the device is a hub */
usb_hub_probe(dev,0); usb_hub_probe(dev, 0);
return 0; return 0;
} }
@ -877,15 +912,15 @@ void usb_scan_devices(void)
struct usb_device *dev; struct usb_device *dev;
/* first make all devices unknown */ /* first make all devices unknown */
for(i=0;i<USB_MAX_DEVICE;i++) { for (i = 0; i < USB_MAX_DEVICE; i++) {
memset(&usb_dev[i],0,sizeof(struct usb_device)); memset(&usb_dev[i], 0, sizeof(struct usb_device));
usb_dev[i].devnum = -1; usb_dev[i].devnum = -1;
} }
dev_index=0; dev_index = 0;
/* device 0 is always present (root hub, so let it analyze) */ /* device 0 is always present (root hub, so let it analyze) */
dev=usb_alloc_new_device(); dev = usb_alloc_new_device();
usb_new_device(dev); usb_new_device(dev);
printf("%d USB Device(s) found\n",dev_index); printf("%d USB Device(s) found\n", dev_index);
/* insert "driver" if possible */ /* insert "driver" if possible */
#ifdef CONFIG_USB_KEYBOARD #ifdef CONFIG_USB_KEYBOARD
drv_usb_kbd_init(); drv_usb_kbd_init();
@ -902,9 +937,9 @@ void usb_scan_devices(void)
#undef USB_HUB_DEBUG #undef USB_HUB_DEBUG
#ifdef USB_HUB_DEBUG #ifdef USB_HUB_DEBUG
#define USB_HUB_PRINTF(fmt,args...) printf (fmt ,##args) #define USB_HUB_PRINTF(fmt, args...) printf (fmt , ##args)
#else #else
#define USB_HUB_PRINTF(fmt,args...) #define USB_HUB_PRINTF(fmt, args...)
#endif #endif
@ -922,19 +957,22 @@ int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
int usb_clear_hub_feature(struct usb_device *dev, int feature) int usb_clear_hub_feature(struct usb_device *dev, int feature)
{ {
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, USB_CNTL_TIMEOUT); USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature,
0, NULL, 0, USB_CNTL_TIMEOUT);
} }
int usb_clear_port_feature(struct usb_device *dev, int port, int feature) int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{ {
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT); USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature,
port, NULL, 0, USB_CNTL_TIMEOUT);
} }
int usb_set_port_feature(struct usb_device *dev, int port, int feature) int usb_set_port_feature(struct usb_device *dev, int port, int feature)
{ {
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT); USB_REQ_SET_FEATURE, USB_RT_PORT, feature,
port, NULL, 0, USB_CNTL_TIMEOUT);
} }
int usb_get_hub_status(struct usb_device *dev, void *data) int usb_get_hub_status(struct usb_device *dev, void *data)
@ -957,27 +995,27 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
int i; int i;
struct usb_device *dev; struct usb_device *dev;
dev=hub->pusb_dev; dev = hub->pusb_dev;
/* Enable power to the ports */ /* Enable power to the ports */
USB_HUB_PRINTF("enabling power on all ports\n"); USB_HUB_PRINTF("enabling power on all ports\n");
for (i = 0; i < dev->maxchild; i++) { for (i = 0; i < dev->maxchild; i++) {
usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
USB_HUB_PRINTF("port %d returns %lX\n",i+1,dev->status); USB_HUB_PRINTF("port %d returns %lX\n", i + 1, dev->status);
wait_ms(hub->desc.bPwrOn2PwrGood * 2); wait_ms(hub->desc.bPwrOn2PwrGood * 2);
} }
} }
void usb_hub_reset(void) void usb_hub_reset(void)
{ {
usb_hub_index=0; usb_hub_index = 0;
} }
struct usb_hub_device *usb_hub_allocate(void) struct usb_hub_device *usb_hub_allocate(void)
{ {
if(usb_hub_index<USB_MAX_HUB) { if (usb_hub_index < USB_MAX_HUB)
return &hub_dev[usb_hub_index++]; return &hub_dev[usb_hub_index++];
}
printf("ERROR: USB_MAX_HUB (%d) reached\n",USB_MAX_HUB); printf("ERROR: USB_MAX_HUB (%d) reached\n", USB_MAX_HUB);
return NULL; return NULL;
} }
@ -990,39 +1028,42 @@ static int hub_port_reset(struct usb_device *dev, int port,
struct usb_port_status portsts; struct usb_port_status portsts;
unsigned short portstatus, portchange; unsigned short portstatus, portchange;
USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port); USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
for(tries=0;tries<MAX_TRIES;tries++) { for (tries = 0; tries < MAX_TRIES; tries++) {
usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
wait_ms(200); wait_ms(200);
if (usb_get_port_status(dev, port + 1, &portsts)<0) { if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed status %lX\n",dev->status); USB_HUB_PRINTF("get_port_status failed status %lX\n",
dev->status);
return -1; return -1;
} }
portstatus = le16_to_cpu(portsts.wPortStatus); portstatus = le16_to_cpu(portsts.wPortStatus);
portchange = le16_to_cpu(portsts.wPortChange); portchange = le16_to_cpu(portsts.wPortChange);
USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus ,portchange, USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed"); portstatus, portchange,
USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d USB_PORT_STAT_ENABLE %d\n", portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? \
"Low Speed" : "High Speed");
USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d" \
" USB_PORT_STAT_ENABLE %d\n",
(portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0, (portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0,
(portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0, (portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0,
(portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0); (portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0);
if ((portchange & USB_PORT_STAT_C_CONNECTION) || if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
!(portstatus & USB_PORT_STAT_CONNECTION)) !(portstatus & USB_PORT_STAT_CONNECTION))
return -1; return -1;
if (portstatus & USB_PORT_STAT_ENABLE) { if (portstatus & USB_PORT_STAT_ENABLE)
break; break;
}
wait_ms(200); wait_ms(200);
} }
if (tries==MAX_TRIES) { if (tries == MAX_TRIES) {
USB_HUB_PRINTF("Cannot enable port %i after %i retries, disabling port.\n", port+1, MAX_TRIES); USB_HUB_PRINTF("Cannot enable port %i after %i retries, " \
"disabling port.\n", port + 1, MAX_TRIES);
USB_HUB_PRINTF("Maybe the USB cable is bad?\n"); USB_HUB_PRINTF("Maybe the USB cable is bad?\n");
return -1; return -1;
} }
@ -1030,7 +1071,6 @@ static int hub_port_reset(struct usb_device *dev, int port,
usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET); usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET);
*portstat = portstatus; *portstat = portstatus;
return 0; return 0;
} }
@ -1041,22 +1081,24 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
unsigned short portstatus, portchange; unsigned short portstatus, portchange;
/* Check status */ /* Check status */
if (usb_get_port_status(dev, port + 1, &portsts)<0) { if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed\n"); USB_HUB_PRINTF("get_port_status failed\n");
return; return;
} }
portstatus = le16_to_cpu(portsts.wPortStatus); portstatus = le16_to_cpu(portsts.wPortStatus);
portchange = le16_to_cpu(portsts.wPortChange); portchange = le16_to_cpu(portsts.wPortChange);
USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange, USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed"); portstatus, portchange,
portstatus&(1 << USB_PORT_FEAT_LOWSPEED) ? \
"Low Speed" : "High Speed");
/* Clear the connection change status */ /* Clear the connection change status */
usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION); usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
/* Disconnect any existing devices under this port */ /* Disconnect any existing devices under this port */
if (((!(portstatus & USB_PORT_STAT_CONNECTION)) && if (((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
(!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) { (!(portstatus & USB_PORT_STAT_ENABLE))) || (dev->children[port])) {
USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n"); USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n");
/* Return now if nothing is connected */ /* Return now if nothing is connected */
if (!(portstatus & USB_PORT_STAT_CONNECTION)) if (!(portstatus & USB_PORT_STAT_CONNECTION))
@ -1073,11 +1115,11 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
wait_ms(200); wait_ms(200);
/* Allocate a new device struct for it */ /* Allocate a new device struct for it */
usb=usb_alloc_new_device(); usb = usb_alloc_new_device();
usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0; usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
dev->children[port] = usb; dev->children[port] = usb;
usb->parent=dev; usb->parent = dev;
/* Run it through the hoops (find a driver, etc) */ /* Run it through the hoops (find a driver, etc) */
if (usb_new_device(usb)) { if (usb_new_device(usb)) {
/* Woops, disable the port */ /* Woops, disable the port */
@ -1096,13 +1138,14 @@ int usb_hub_configure(struct usb_device *dev)
struct usb_hub_device *hub; struct usb_hub_device *hub;
/* "allocate" Hub device */ /* "allocate" Hub device */
hub=usb_hub_allocate(); hub = usb_hub_allocate();
if(hub==NULL) if (hub == NULL)
return -1; return -1;
hub->pusb_dev=dev; hub->pusb_dev = dev;
/* Get the the hub descriptor */ /* Get the the hub descriptor */
if (usb_get_hub_descriptor(dev, buffer, 4) < 0) { if (usb_get_hub_descriptor(dev, buffer, 4) < 0) {
USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor, giving up %lX\n",dev->status); USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \
"descriptor, giving up %lX\n", dev->status);
return -1; return -1;
} }
descriptor = (struct usb_hub_descriptor *)buffer; descriptor = (struct usb_hub_descriptor *)buffer;
@ -1110,43 +1153,48 @@ int usb_hub_configure(struct usb_device *dev)
/* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */ /* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */
i = descriptor->bLength; i = descriptor->bLength;
if (i > USB_BUFSIZ) { if (i > USB_BUFSIZ) {
USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor - too long: %d\n", USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \
descriptor->bLength); "descriptor - too long: %d\n",
descriptor->bLength);
return -1; return -1;
} }
if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) { if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) {
USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor 2nd giving up %lX\n",dev->status); USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \
"descriptor 2nd giving up %lX\n", dev->status);
return -1; return -1;
} }
memcpy((unsigned char *)&hub->desc,buffer,descriptor->bLength); memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength);
/* adjust 16bit values */ /* adjust 16bit values */
hub->desc.wHubCharacteristics = le16_to_cpu(descriptor->wHubCharacteristics); hub->desc.wHubCharacteristics =
le16_to_cpu(descriptor->wHubCharacteristics);
/* set the bitmap */ /* set the bitmap */
bitmap=(unsigned char *)&hub->desc.DeviceRemovable[0]; bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0];
memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* devices not removable by default */ /* devices not removable by default */
bitmap=(unsigned char *)&hub->desc.PortPowerCtrlMask[0]; memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8);
memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */ bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0];
for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) { memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */
hub->desc.DeviceRemovable[i]=descriptor->DeviceRemovable[i];
} for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++)
for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) { hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i];
hub->desc.DeviceRemovable[i]=descriptor->PortPowerCtrlMask[i];
} for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++)
hub->desc.DeviceRemovable[i] = descriptor->PortPowerCtrlMask[i];
dev->maxchild = descriptor->bNbrPorts; dev->maxchild = descriptor->bNbrPorts;
USB_HUB_PRINTF("%d ports detected\n", dev->maxchild); USB_HUB_PRINTF("%d ports detected\n", dev->maxchild);
switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) { switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) {
case 0x00: case 0x00:
USB_HUB_PRINTF("ganged power switching\n"); USB_HUB_PRINTF("ganged power switching\n");
break; break;
case 0x01: case 0x01:
USB_HUB_PRINTF("individual port power switching\n"); USB_HUB_PRINTF("individual port power switching\n");
break; break;
case 0x02: case 0x02:
case 0x03: case 0x03:
USB_HUB_PRINTF("unknown reserved power switching mode\n"); USB_HUB_PRINTF("unknown reserved power switching mode\n");
break; break;
} }
if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND) if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND)
@ -1155,40 +1203,52 @@ int usb_hub_configure(struct usb_device *dev)
USB_HUB_PRINTF("standalone hub\n"); USB_HUB_PRINTF("standalone hub\n");
switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) { switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) {
case 0x00: case 0x00:
USB_HUB_PRINTF("global over-current protection\n"); USB_HUB_PRINTF("global over-current protection\n");
break; break;
case 0x08: case 0x08:
USB_HUB_PRINTF("individual port over-current protection\n"); USB_HUB_PRINTF("individual port over-current protection\n");
break; break;
case 0x10: case 0x10:
case 0x18: case 0x18:
USB_HUB_PRINTF("no over-current protection\n"); USB_HUB_PRINTF("no over-current protection\n");
break; break;
} }
USB_HUB_PRINTF("power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2);
USB_HUB_PRINTF("hub controller current requirement: %dmA\n", descriptor->bHubContrCurrent); USB_HUB_PRINTF("power on to power good time: %dms\n",
descriptor->bPwrOn2PwrGood * 2);
USB_HUB_PRINTF("hub controller current requirement: %dmA\n",
descriptor->bHubContrCurrent);
for (i = 0; i < dev->maxchild; i++) for (i = 0; i < dev->maxchild; i++)
USB_HUB_PRINTF("port %d is%s removable\n", i + 1, USB_HUB_PRINTF("port %d is%s removable\n", i + 1,
hub->desc.DeviceRemovable[(i + 1)/8] & (1 << ((i + 1)%8)) ? " not" : ""); hub->desc.DeviceRemovable[(i + 1) / 8] & \
(1 << ((i + 1) % 8)) ? " not" : "");
if (sizeof(struct usb_hub_status) > USB_BUFSIZ) { if (sizeof(struct usb_hub_status) > USB_BUFSIZ) {
USB_HUB_PRINTF("usb_hub_configure: failed to get Status - too long: %d\n", USB_HUB_PRINTF("usb_hub_configure: failed to get Status - " \
descriptor->bLength); "too long: %d\n", descriptor->bLength);
return -1; return -1;
} }
if (usb_get_hub_status(dev, buffer) < 0) { if (usb_get_hub_status(dev, buffer) < 0) {
USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",dev->status); USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",
dev->status);
return -1; return -1;
} }
hubsts = (struct usb_hub_status *)buffer; hubsts = (struct usb_hub_status *)buffer;
USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n", USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n",
le16_to_cpu(hubsts->wHubStatus),le16_to_cpu(hubsts->wHubChange)); le16_to_cpu(hubsts->wHubStatus),
le16_to_cpu(hubsts->wHubChange));
USB_HUB_PRINTF("local power source is %s\n", USB_HUB_PRINTF("local power source is %s\n",
(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? \
"lost (inactive)" : "good");
USB_HUB_PRINTF("%sover-current condition exists\n", USB_HUB_PRINTF("%sover-current condition exists\n",
(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no "); (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \
"" : "no ");
usb_hub_power_on(hub); usb_hub_power_on(hub);
for (i = 0; i < dev->maxchild; i++) { for (i = 0; i < dev->maxchild; i++) {
struct usb_port_status portsts; struct usb_port_status portsts;
unsigned short portstatus, portchange; unsigned short portstatus, portchange;
@ -1197,41 +1257,51 @@ int usb_hub_configure(struct usb_device *dev)
USB_HUB_PRINTF("get_port_status failed\n"); USB_HUB_PRINTF("get_port_status failed\n");
continue; continue;
} }
portstatus = le16_to_cpu(portsts.wPortStatus); portstatus = le16_to_cpu(portsts.wPortStatus);
portchange = le16_to_cpu(portsts.wPortChange); portchange = le16_to_cpu(portsts.wPortChange);
USB_HUB_PRINTF("Port %d Status %X Change %X\n",i+1,portstatus,portchange); USB_HUB_PRINTF("Port %d Status %X Change %X\n",
i + 1, portstatus, portchange);
if (portchange & USB_PORT_STAT_C_CONNECTION) { if (portchange & USB_PORT_STAT_C_CONNECTION) {
USB_HUB_PRINTF("port %d connection change\n", i + 1); USB_HUB_PRINTF("port %d connection change\n", i + 1);
usb_hub_port_connect_change(dev, i); usb_hub_port_connect_change(dev, i);
} }
if (portchange & USB_PORT_STAT_C_ENABLE) { if (portchange & USB_PORT_STAT_C_ENABLE) {
USB_HUB_PRINTF("port %d enable change, status %x\n", i + 1, portstatus); USB_HUB_PRINTF("port %d enable change, status %x\n",
usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); i + 1, portstatus);
usb_clear_port_feature(dev, i + 1,
USB_PORT_FEAT_C_ENABLE);
/* EM interference sometimes causes bad shielded USB devices to /* EM interference sometimes causes bad shielded USB
* be shutdown by the hub, this hack enables them again. * devices to be shutdown by the hub, this hack enables
* Works at least with mouse driver */ * them again. Works at least with mouse driver */
if (!(portstatus & USB_PORT_STAT_ENABLE) && if (!(portstatus & USB_PORT_STAT_ENABLE) &&
(portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) { (portstatus & USB_PORT_STAT_CONNECTION) &&
USB_HUB_PRINTF("already running port %i disabled by hub (EMI?), re-enabling...\n", ((dev->children[i]))) {
i + 1); USB_HUB_PRINTF("already running port %i " \
"disabled by hub (EMI?), " \
"re-enabling...\n", i + 1);
usb_hub_port_connect_change(dev, i); usb_hub_port_connect_change(dev, i);
} }
} }
if (portstatus & USB_PORT_STAT_SUSPEND) { if (portstatus & USB_PORT_STAT_SUSPEND) {
USB_HUB_PRINTF("port %d suspend change\n", i + 1); USB_HUB_PRINTF("port %d suspend change\n", i + 1);
usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_SUSPEND); usb_clear_port_feature(dev, i + 1,
USB_PORT_FEAT_SUSPEND);
} }
if (portchange & USB_PORT_STAT_C_OVERCURRENT) { if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
USB_HUB_PRINTF("port %d over-current change\n", i + 1); USB_HUB_PRINTF("port %d over-current change\n", i + 1);
usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); usb_clear_port_feature(dev, i + 1,
USB_PORT_FEAT_C_OVER_CURRENT);
usb_hub_power_on(hub); usb_hub_power_on(hub);
} }
if (portchange & USB_PORT_STAT_C_RESET) { if (portchange & USB_PORT_STAT_C_RESET) {
USB_HUB_PRINTF("port %d reset change\n", i + 1); USB_HUB_PRINTF("port %d reset change\n", i + 1);
usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); usb_clear_port_feature(dev, i + 1,
USB_PORT_FEAT_C_RESET);
} }
} /* end for i all ports */ } /* end for i all ports */
@ -1265,7 +1335,7 @@ int usb_hub_probe(struct usb_device *dev, int ifnum)
return 0; return 0;
/* We found a hub */ /* We found a hub */
USB_HUB_PRINTF("USB hub found\n"); USB_HUB_PRINTF("USB hub found\n");
ret=usb_hub_configure(dev); ret = usb_hub_configure(dev);
return ret; return ret;
} }

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,41 @@ static int cc_to_error[16] = {
/* Not Access */ -1 /* Not Access */ -1
}; };
static const char *cc_to_string[16] = {
"No Error",
"CRC: Last data packet from endpoint contained a CRC error.",
"BITSTUFFING: Last data packet from endpoint contained a bit " \
"stuffing violation",
"DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \
"that did not match the expected value.",
"STALL: TD was moved to the Done Queue because the endpoint returned" \
" a STALL PID",
"DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \
"not provide a handshake (OUT)",
"PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\
"(IN) or handshake (OUT)",
"UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \
"value is not defined.",
"DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \
"either the size of the maximum data packet allowed\n" \
"from the endpoint (found in MaximumPacketSize field\n" \
"of ED) or the remaining buffer size.",
"DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \
"and that amount was not sufficient to fill the\n" \
"specified buffer",
"reserved1",
"reserved2",
"BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \
"than it could be written to system memory",
"BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \
"system memory fast enough to keep up with data USB " \
"data rate.",
"NOT ACCESSED: This code is set by software before the TD is placed" \
"on a list to be processed by the HC.(1)",
"NOT ACCESSED: This code is set by software before the TD is placed" \
"on a list to be processed by the HC.(2)",
};
/* ED States */ /* ED States */
#define ED_NEW 0x00 #define ED_NEW 0x00