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

📄 usb.c

📁 u-boot-1.1.6 源码包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * * Most of this source has been derived from the Linux USB * project: * (C) Copyright Linus Torvalds 1999 * (C) Copyright Johannes Erdfelt 1999-2001 * (C) Copyright Andreas Gal 1999 * (C) Copyright Gregory P. Smith 1999 * (C) Copyright Deti Fliegl 1999 (new USB architecture) * (C) Copyright Randy Dunlap 2000 * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id) * (C) Copyright Yggdrasil Computing, Inc. 2000 *     (usb_device_id matching changes by Adam J. Richter) * * Adapted for U-Boot: * (C) Copyright 2001 Denis Peter, MPL AG Switzerland * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * *//* * How it works: * * Since this is a bootloader, the devices will not be automatic * (re)configured on hotplug, but after a restart of the USB the * device should work. * * For each transfer (except "Interrupt") we wait for completion. */#include <common.h>#include <command.h>#include <asm/processor.h>#include <linux/ctype.h>#if (CONFIG_COMMANDS & CFG_CMD_USB)#include <usb.h>#ifdef CONFIG_4xx#include <405gp_pci.h>#endif#undef USB_DEBUG#ifdef	USB_DEBUG#define	USB_PRINTF(fmt,args...)	printf (fmt ,##args)#else#define USB_PRINTF(fmt,args...)#endif#define USB_BUFSIZ	512static struct usb_device usb_dev[USB_MAX_DEVICE];static int dev_index;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... */void usb_scan_devices(void);int usb_hub_probe(struct usb_device *dev, int ifnum);void usb_hub_reset(void);/*********************************************************************** * wait_ms */void __inline__ wait_ms(unsigned long ms){	while(ms-->0)		udelay(1000);}/*************************************************************************** * Init USB Device */int usb_init(void){	int result;	running=0;	dev_index=0;	asynch_allowed=1;	usb_hub_reset();	/* init low_level USB */	printf("USB:   ");	result = usb_lowlevel_init();	/* if lowlevel init is OK, scan the bus for devices i.e. search HUBs and configure them */	if(result==0) {		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;	}}/****************************************************************************** * Stop USB this stops the LowLevel Part and deregisters USB devices. */int usb_stop(void){	asynch_allowed=1;	usb_started = 0;	usb_hub_reset();	return usb_lowlevel_stop();}/* * disables the asynch behaviour of the control message. This is used for data * transfers that uses the exclusiv access to the control and bulk messages. */void usb_disable_asynch(int disable){	asynch_allowed=!disable;}/*------------------------------------------------------------------- * Message wrappers. * *//* * submits an Interrupt Message */int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,			void *buffer,int transfer_len, int interval){	return submit_int_msg(dev,pipe,buffer,transfer_len,interval);}/* * submits a control message and waits for comletion (at least timeout * 1ms) * If timeout is 0, we don't wait for completion (used as example to set and * clear keyboards LEDs). For data transfers, (storage transfers) we don't * allow control messages with 0 timeout, by previousely resetting the flag * asynch_allowed (usb_disable_asynch(1)). * returns the transfered length if OK or -1 if error. The transfered length * and the current status are stored in the dev->act_len and dev->status. */int usb_control_msg(struct usb_device *dev, unsigned int pipe,			unsigned char request, unsigned char requesttype,			unsigned short value, unsigned short index,			void *data, unsigned short size, int timeout){	if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */		return -1;	/* set setup command */	setup_packet.requesttype = requesttype;	setup_packet.request = request;	setup_packet.value = swap_16(value);	setup_packet.index = swap_16(index);	setup_packet.length = swap_16(size); 	USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X\nvalue 0x%X index 0x%X length 0x%X\n",		request,requesttype,value,index,size);	dev->status=USB_ST_NOT_PROC; /*not yet processed */	submit_control_msg(dev,pipe,data,size,&setup_packet);	if(timeout==0) {		return (int)size;	}	while(timeout--) {		if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))			break;		wait_ms(1);	}	if(dev->status==0)		return dev->act_len;	else {		return -1;	}}/*------------------------------------------------------------------- * submits bulk message, and waits for completion. returns 0 if Ok or * -1 if Error. * synchronous behavior */int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,			void *data, int len, int *actual_length, int timeout){	if (len < 0)		return -1;	dev->status=USB_ST_NOT_PROC; /*not yet processed */	submit_bulk_msg(dev,pipe,data,len);	while(timeout--) {		if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))			break;		wait_ms(1);	}	*actual_length=dev->act_len;	if(dev->status==0)		return 0;	else		return -1;}/*------------------------------------------------------------------- * Max Packet stuff *//* * returns the max packet size, depending on the pipe direction and * the configurations values */int usb_maxpacket(struct usb_device *dev,unsigned long pipe){	if((pipe & USB_DIR_IN)==0) /* direction is out -> use emaxpacket out */		return(dev->epmaxpacketout[((pipe>>15) & 0xf)]);	else		return(dev->epmaxpacketin[((pipe>>15) & 0xf)]);}/* * set the max packed value of all endpoints in the given configuration */int usb_set_maxpacket(struct usb_device *dev){	int i,ii,b;	struct usb_endpoint_descriptor *ep;	for(i=0; i<dev->config.bNumInterfaces;i++) {		for(ii=0; ii<dev->config.if_desc[i].bNumEndpoints; ii++) {			ep=&dev->config.if_desc[i].ep_desc[ii];			b=ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;			if((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)==USB_ENDPOINT_XFER_CONTROL) {	/* Control => bidirectional */				dev->epmaxpacketout[b] = ep->wMaxPacketSize;				dev->epmaxpacketin [b] = ep->wMaxPacketSize;				USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",b,dev->epmaxpacketin[b]);			}			else {				if ((ep->bEndpointAddress & 0x80)==0) { /* OUT Endpoint */					if(ep->wMaxPacketSize > dev->epmaxpacketout[b]) {						dev->epmaxpacketout[b] = ep->wMaxPacketSize;						USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",b,dev->epmaxpacketout[b]);					}				}				else  { /* IN Endpoint */					if(ep->wMaxPacketSize > dev->epmaxpacketin[b]) {						dev->epmaxpacketin[b] = ep->wMaxPacketSize;						USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",b,dev->epmaxpacketin[b]);					}				} /* if out */			} /* if control */		} /* for each endpoint */	}	return 0;}/******************************************************************************* * Parse the config, located in buffer, and fills the dev->config structure. * Note that all little/big endian swapping are done automatically. */int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno){	struct usb_descriptor_header *head;	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;	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) {		switch(head->bDescriptorType) {			case USB_DT_INTERFACE:				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;				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);				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;		head = (struct usb_descriptor_header *)&buffer[index];	}	return 1;}/*********************************************************************** * Clears an endpoint * endp: endpoint number in bits 0-3; * direction flag in bit 7 (1 = IN, 0 = OUT) */int usb_clear_halt(struct usb_device *dev, int pipe){	int result;	int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3);	/* don't clear if failed */	if (result < 0)		return result;	/*	 * NOTE: we do not get status and verify reset was successful	 * as some devices are reported to lock up upon this check..	 */	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));	/* toggle is reset on clear */	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);	return 0;}/********************************************************************** * get_descriptor type */int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size){	int res; 	res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,			(type << 8) + index, 0,			buf, size, USB_CNTL_TIMEOUT);	return res;}/********************************************************************** * gets configuration cfgno and store it in the buffer */int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno){ 	int result;	unsigned int tmp;	struct usb_config_descriptor *config;	config=(struct usb_config_descriptor *)&buffer[0];	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);	if (result < 8) {		if (result < 0)			printf("unable to get descriptor, error %lX\n",dev->status);		else			printf("config descriptor too short (expected %i, got %i)\n",8,result);		return -1;	}	tmp=swap_16(config->wTotalLength);	if (tmp > USB_BUFSIZ) {

⌨️ 快捷键说明

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