⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif}/**************************************************************************** * HUB "Driver" * Probes device for being a hub and configurate it */#undef	USB_HUB_DEBUG#ifdef	USB_HUB_DEBUG#define	USB_HUB_PRINTF(fmt,args...)	printf (fmt ,##args)#else#define USB_HUB_PRINTF(fmt,args...)#endifstatic struct usb_hub_device hub_dev[USB_MAX_HUB];static int usb_hub_index;int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,		USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT);}int usb_clear_hub_feature(struct usb_device *dev, int feature){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		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){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		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){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		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){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),			USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,			data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);}int usb_get_port_status(struct usb_device *dev, int port, void *data){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),			USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,			data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);}static void usb_hub_power_on(struct usb_hub_device *hub){	int i;	struct usb_device *dev;	dev=hub->pusb_dev;	/* Enable power to the ports */	USB_HUB_PRINTF("enabling power on all ports\n");	for (i = 0; i < dev->maxchild; i++) {		usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);		USB_HUB_PRINTF("port %d returns %lX\n",i+1,dev->status);		wait_ms(hub->desc.bPwrOn2PwrGood * 2);	}}void usb_hub_reset(void){	usb_hub_index=0;}struct usb_hub_device *usb_hub_allocate(void){	if(usb_hub_index<USB_MAX_HUB) {		return &hub_dev[usb_hub_index++];	}	printf("ERROR: USB_MAX_HUB (%d) reached\n",USB_MAX_HUB);	return NULL;}#define MAX_TRIES 5void usb_hub_port_connect_change(struct usb_device *dev, int port){	struct usb_device *usb;	struct usb_port_status portsts;	unsigned short portstatus, portchange;	int tries;	/* Check status */	if (usb_get_port_status(dev, port + 1, &portsts)<0) {		USB_HUB_PRINTF("get_port_status failed\n");		return;	}	portstatus = swap_16(portsts.wPortStatus);	portchange = swap_16(portsts.wPortChange);	USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange,		portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");	/* Clear the connection change status */	usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);	/* Disconnect any existing devices under this port */	if (((!(portstatus & USB_PORT_STAT_CONNECTION)) &&	     (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) {		USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n");		/* Return now if nothing is connected */		if (!(portstatus & USB_PORT_STAT_CONNECTION))			return;	}	wait_ms(200);	/* Reset the port */	for(tries=0;tries<MAX_TRIES;tries++) {		usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);		wait_ms(200);		if (usb_get_port_status(dev, port + 1, &portsts)<0) {			USB_HUB_PRINTF("get_port_status failed status %lX\n",dev->status);			return;		}		portstatus = swap_16(portsts.wPortStatus);		portchange = swap_16(portsts.wPortChange);		USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus ,portchange,			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,			(portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0,			(portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0);		if ((portchange & USB_PORT_STAT_C_CONNECTION) ||		    !(portstatus & USB_PORT_STAT_CONNECTION))			return;		if (portstatus & USB_PORT_STAT_ENABLE)			break;		wait_ms(200);	}	if (tries==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");		return;	}	usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET);	wait_ms(200);	/* Allocate a new device struct for it */	usb=usb_alloc_new_device();	usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;	dev->children[port] = usb;	usb->parent=dev;	/* Run it through the hoops (find a driver, etc) */	if (usb_new_device(usb)) {		/* Woops, disable the port */		USB_HUB_PRINTF("hub: disabling port %d\n", port + 1);		usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);	}}int usb_hub_configure(struct usb_device *dev){	unsigned char buffer[USB_BUFSIZ], *bitmap;	struct usb_hub_descriptor *descriptor;	struct usb_hub_status *hubsts;	int i;	struct usb_hub_device *hub;	/* "allocate" Hub device */	hub=usb_hub_allocate();	if(hub==NULL)		return -1;	hub->pusb_dev=dev;	/* Get the the hub descriptor */	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);		return -1;	}	descriptor = (struct usb_hub_descriptor *)buffer;	/* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */	i = descriptor->bLength;	if (i > USB_BUFSIZ) {		USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor - too long: %d\N",			descriptor->bLength);		return -1;	}	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);		return -1;	}	memcpy((unsigned char *)&hub->desc,buffer,descriptor->bLength);	/* adjust 16bit values */	hub->desc.wHubCharacteristics=swap_16(descriptor->wHubCharacteristics);	/* set the bitmap */	bitmap=(unsigned char *)&hub->desc.DeviceRemovable[0];	memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* devices not removable by default */	bitmap=(unsigned char *)&hub->desc.PortPowerCtrlMask[0];	memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */	for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) {		hub->desc.DeviceRemovable[i]=descriptor->DeviceRemovable[i];	}	for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) {		hub->desc.DeviceRemovable[i]=descriptor->PortPowerCtrlMask[i];	}	dev->maxchild = descriptor->bNbrPorts;	USB_HUB_PRINTF("%d ports detected\n", dev->maxchild);	switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) {		case 0x00:			USB_HUB_PRINTF("ganged power switching\n");			break;		case 0x01:			USB_HUB_PRINTF("individual port power switching\n");			break;		case 0x02:		case 0x03:			USB_HUB_PRINTF("unknown reserved power switching mode\n");			break;	}	if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND)		USB_HUB_PRINTF("part of a compound device\n");	else		USB_HUB_PRINTF("standalone hub\n");	switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) {		case 0x00:			USB_HUB_PRINTF("global over-current protection\n");			break;		case 0x08:			USB_HUB_PRINTF("individual port over-current protection\n");			break;		case 0x10:		case 0x18:			USB_HUB_PRINTF("no over-current protection\n");      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);	for (i = 0; i < dev->maxchild; i++)		USB_HUB_PRINTF("port %d is%s removable\n", i + 1,			hub->desc.DeviceRemovable[(i + 1)/8] & (1 << ((i + 1)%8)) ? " not" : "");	if (sizeof(struct usb_hub_status) > USB_BUFSIZ) {		USB_HUB_PRINTF("usb_hub_configure: failed to get Status - too long: %d\n",			descriptor->bLength);		return -1;	}	if (usb_get_hub_status(dev, buffer) < 0) {		USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",dev->status);		return -1;	}	hubsts = (struct usb_hub_status *)buffer;	USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n",		swap_16(hubsts->wHubStatus),swap_16(hubsts->wHubChange));	USB_HUB_PRINTF("local power source is %s\n",		(swap_16(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");	USB_HUB_PRINTF("%sover-current condition exists\n",		(swap_16(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no ");	usb_hub_power_on(hub);	for (i = 0; i < dev->maxchild; i++) {		struct usb_port_status portsts;		unsigned short portstatus, portchange;		if (usb_get_port_status(dev, i + 1, &portsts) < 0) {			USB_HUB_PRINTF("get_port_status failed\n");			continue;		}		portstatus = swap_16(portsts.wPortStatus);		portchange = swap_16(portsts.wPortChange);		USB_HUB_PRINTF("Port %d Status %X Change %X\n",i+1,portstatus,portchange);		if (portchange & USB_PORT_STAT_C_CONNECTION) {			USB_HUB_PRINTF("port %d connection change\n", i + 1);			usb_hub_port_connect_change(dev, i);		}		if (portchange & USB_PORT_STAT_C_ENABLE) {			USB_HUB_PRINTF("port %d enable change, status %x\n", i + 1, portstatus);			usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);			/* EM interference sometimes causes bad shielded USB devices to			 * be shutdown by the hub, this hack enables them again.			 * Works at least with mouse driver */			if (!(portstatus & USB_PORT_STAT_ENABLE) &&				(portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) {				USB_HUB_PRINTF("already running port %i disabled by hub (EMI?), re-enabling...\n",					i + 1);					usb_hub_port_connect_change(dev, i);			}		}		if (portstatus & USB_PORT_STAT_SUSPEND) {			USB_HUB_PRINTF("port %d suspend change\n", i + 1);			usb_clear_port_feature(dev, i + 1,  USB_PORT_FEAT_SUSPEND);		}		if (portchange & USB_PORT_STAT_C_OVERCURRENT) {			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_hub_power_on(hub);		}		if (portchange & USB_PORT_STAT_C_RESET) {			USB_HUB_PRINTF("port %d reset change\n", i + 1);			usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);		}	} /* end for i all ports */	return 0;}int usb_hub_probe(struct usb_device *dev, int ifnum){	struct usb_interface_descriptor *iface;	struct usb_endpoint_descriptor *ep;	int ret;	iface = &dev->config.if_desc[ifnum];	/* Is it a hub? */	if (iface->bInterfaceClass != USB_CLASS_HUB)		return 0;	/* Some hubs have a subclass of 1, which AFAICT according to the */	/*  specs is not defined, but it works */	if ((iface->bInterfaceSubClass != 0) &&	    (iface->bInterfaceSubClass != 1))		return 0;	/* Multiple endpoints? What kind of mutant ninja-hub is this? */	if (iface->bNumEndpoints != 1)		return 0;	ep = &iface->ep_desc[0];	/* Output endpoint? Curiousier and curiousier.. */	if (!(ep->bEndpointAddress & USB_DIR_IN))		return 0;	/* If it's not an interrupt endpoint, we'd better punt! */	if ((ep->bmAttributes & 3) != 3)		return 0;	/* We found a hub */	USB_HUB_PRINTF("USB hub found\n");	ret=usb_hub_configure(dev);	return ret;}#endif /* (CONFIG_COMMANDS & CFG_CMD_USB) *//* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -