www.pudn.com > arm_uDisk.rar > USBSETUP.C


/************************************************************** 
 NAME: usbsetup.c 
 DESC: process the USB setup stage operations. 
 HISTORY: 
 MAR.25.2002:purnnamu: S3C2400X usbsetup.c is ported for S3C2410X. 
 AUG.20.2002:purnnamu: rEP0_CSR should be used instead of rOUT_CSR1_REG for EP0 macros. 
***************************************************************/ 
 
#include  
#include "option.h" 
#include "2410addr.h" 
#include "2410lib.h" 
#include "def.h" 
 
 
#include "2410usb.h" 
#include "usbmain.h" 
#include "usb.h" 
#include "usblib.h" 
#include "usbsetup.h" 
 
// *** End point information *** 
//   EP0: control 
//   EP1: bulk in end point 
//   EP2: not used 
//   EP3: bulk out end point 
//   EP4: not used 
 
// *** VERY IMPORTANT NOTE *** 
// Every descriptor size of EP0 should be 8n+m(m=1~7). 
// Otherwise, USB will not operate normally because the program 
// doesn't prepare the case that the descriptor size is 8n+0. 
// If the size of a descriptor is 8n, the 0 length packit should be sent.  
// Special thanks to E.S.Choi for reminding me of this USB specification. 
 
 
// =================================================================== 
// All following commands will operate only in case  
// - ep0_csr is valid. 
// =================================================================== 
#define CLR_EP0_OUT_PKT_RDY() 		rEP0_CSR=( ep0_csr & (~EP0_WR_BITS)| \ 
						EP0_SERVICED_OUT_PKT_RDY )	  
#define CLR_EP0_OUTPKTRDY_DATAEND() 	rEP0_CSR=( ep0_csr & (~EP0_WR_BITS)| \ 
						(EP0_SERVICED_OUT_PKT_RDY|EP0_DATA_END) )	  
					 
#define SET_EP0_IN_PKT_RDY() 		rEP0_CSR=( ep0_csr & (~EP0_WR_BITS)| \ 
						(EP0_IN_PKT_READY) )	  
#define SET_EP0_INPKTRDY_DATAEND() 	rEP0_CSR=( ep0_csr & (~EP0_WR_BITS)| \ 
						(EP0_IN_PKT_READY|EP0_DATA_END) )	  
					 
#define CLR_EP0_SETUP_END() 		rEP0_CSR=( ep0_csr & (~EP0_WR_BITS)| \ 
						(EP0_SERVICED_SETUP_END) ) 
 
#define CLR_EP0_SENT_STALL() 		rEP0_CSR=( ep0_csr & (~EP0_WR_BITS)& \ 
						(~EP0_SENT_STALL) ) 
 
#define FLUSH_EP0_FIFO() 		{while(rOUT_FIFO_CNT1_REG)rEP0_FIFO;} 
 
U32 ep0State; //U32=Unsigned int (32bit) 
U32 ep0SubState; 
 
extern volatile int isUsbdSetConfiguration; 
 
struct USB_SETUP_DATA descSetup; 
struct USB_DEVICE_DESCRIPTOR descDev; 
struct USB_CONFIGURATION_DESCRIPTOR descConf; 
struct USB_INTERFACE_DESCRIPTOR descIf; 
struct USB_ENDPOINT_DESCRIPTOR descEndpt0; 
struct USB_ENDPOINT_DESCRIPTOR descEndpt1; 
 
 
static const U8 descStr0[]={ 
	4,STRING_TYPE,LANGID_US_L,LANGID_US_H,  //codes representing languages 
    };//Total 4 string 
     
#ifdef _FOR_UDISK_ 
static const U8 descStr1_1[18]=                         //设备序列号 
{0x12,0x03,0x32,0x00,0x30,0x00,0x37,0x00,0x31,0x00,0x30,0x00,0x39,0x00,0x38,0x00,0x32,0x00}; 
static const U8 descStr2_1[]={  //Product   
	 (0x2a+2+2),STRING_TYPE,  
        'U',0x0,'S',0x0,'B',0x0,' ',0x0,'M',0x0,'a',0x0,'s',0x0,'s',0x0, 
        ' ',0x0,'S',0x0,'t',0x0,'o',0x0,'r',0x0,'a',0x0,'g',0x0,'e',0x0, 
        ' ',0x0,'D',0x0,'e',0x0,'v',0x0,'i',0x0,'c',0x0,'e',0x0 
    };//Total 46 string 
#endif 
/* 
#define STRING_TYPE=(3) 
#define LANGID_US_L=(0x09)   
#define LANGID_US_H=(0x04) 
*/ 
 
static const U8 descStr1[]={  //Manufacturer   
        (0x14+2),STRING_TYPE,  
        'S',0x0,'y',0x0,'s',0x0,'t',0x0,'e',0x0,'m',0x0,' ',0x0,'M',0x0, 
        'C',0x0,'U',0x0, 
    };//Total 22 string 
     
static const U8 descStr2[]={  //Product   
	 (0x2a+2+2),STRING_TYPE,  
        'U',0x0,'S',0x0,'B',0x0,' ',0x0,'M',0x0,'a',0x0,'s',0x0,'s',0x0, 
        ' ',0x0,'S',0x0,'t',0x0,'o',0x0,'r',0x0,'a',0x0,'g',0x0,'e',0x0, 
        ' ',0x0,'D',0x0,'e',0x0,'v',0x0,'i',0x0,'c',0x0,'e',0x0 
    };//Total 44 string 
 
void Ep0Handler(void) 
{ 
    static int ep0SubState; 
    int i; 
    U8 ep0_csr; 
#ifdef _FOR_UDISK_ 
	unsigned char max_LUN=0;          //只有一个逻辑单元 
#endif 
 
    rINDEX_REG=0; 
    ep0_csr=rEP0_CSR;//Push to buffer 
     
    //DbgPrintf("<0:%x]",ep0_csr); 
 
    //DATAEND interrupt(ep0_csr==0x0) will be ignored  
    //because ep0State==EP0_STATE_INIT when the DATAEND interrupt is issued. 
 
     
    if(ep0_csr & EP0_SETUP_END)//define EP0_SETUP_END=0x10 
    {    
    	 // Host may end GET_DESCRIPTOR operation without completing the IN data stage. 
    	 // If host does that, SETUP_END bit will be set. 
    	 // OUT_PKT_RDY has to be also cleared because status stage sets OUT_PKT_RDY to 1. 
   		//DbgPrintf("[SETUPEND]"); 
		CLR_EP0_SETUP_END(); 
		if(ep0_csr & EP0_OUT_PKT_READY)  
		{ 
		    FLUSH_EP0_FIFO(); //(???) 
		    //I think this isn't needed because EP0 flush is done automatically.    
		    CLR_EP0_OUT_PKT_RDY(); 
		} 
	 
		ep0State=EP0_STATE_INIT;//#define EP0_STATE_INIT=0 
		return; 
    }	 
 
    //I think that EP0_SENT_STALL will not be set to 1. 
    if(ep0_csr & EP0_SENT_STALL) 
    {    
 	  	//DbgPrintf("[STALL]"); 
 	  	CLR_EP0_SENT_STALL(); 
		if(ep0_csr & EP0_OUT_PKT_READY)  
		{ 
		    CLR_EP0_OUT_PKT_RDY(); 
		} 
	 
		ep0State=EP0_STATE_INIT;//#define EP0_STATE_INIT=0 
		return; 
    }	 
 
 
    if((ep0_csr & EP0_OUT_PKT_READY) && (ep0State==EP0_STATE_INIT)) 
    {	 
		RdPktEp0((U8 *)&descSetup,EP0_PKT_SIZE);//Read data from EP0_FIFO 
#ifdef _FOR_UDISK_ 
		CLR_EP0_OUT_PKT_RDY(); 
#endif 
 
		//PrintEp0Pkt((U8 *)(&descSetup)); //DEBUG 
     
	switch(descSetup.bRequest)//SW1 
    	{ 
	#ifdef _FOR_UDISK_ 
	case 0xFE: 
		//	CLR_EP0_OUT_PKT_RDY(); 
		if(USBD_flg==1) 
		{ 
			if(descSetup.bmRequestType==0xA1) 
		   	{ 
		   		 WrPktEp0((U8 *)&max_LUN,1); 
		        	SET_EP0_IN_PKT_RDY(); 
		   	} 
		} 
			break; 
	#endif 
    	case GET_DESCRIPTOR://0x06 
		switch(descSetup.bValueH)//SW2       
		{ 
			case DEVICE_TYPE://0x01 
	 	    		//DbgPrintf("[GDD]"); 
	 	    		#ifndef _FOR_UDISK_ 
	 	    			CLR_EP0_OUT_PKT_RDY(); 
				#endif 
		    		ep0State=EP0_STATE_GD_DEV_0;	         
		    		break;	 
			case CONFIGURATION_TYPE://0x02 
	 	    		//DbgPrintf("[GDC]"); 
	 	    		#ifndef _FOR_UDISK_ 
	 	    			CLR_EP0_OUT_PKT_RDY(); 
				#endif 
	 	    		if((descSetup.bLengthL+(descSetup.bLengthH<<8))>0x09) 
	 	    		  //bLengthH should be used for bLength=0x209 at WIN2K.    	 
		    			ep0State=EP0_STATE_GD_CFG_0; //for WIN98,WIN2K 
				else	    	     
	  				ep0State=EP0_STATE_GD_CFG_ONLY_0; //for WIN2K 
		    		break; 
   			case STRING_TYPE://0x03 
	 	    		//DbgPrintf("[GDS]"); 
	 	    		#ifndef _FOR_UDISK_ 
	 	    			CLR_EP0_OUT_PKT_RDY(); 
				#endif 
		    		switch(descSetup.bValueL)//SW3 
		    		{ 
			    		case 0: 
				    	    	ep0State=EP0_STATE_GD_STR_I0; 
				    	    	break; 
			    		case 1: 
		       	    	    ep0State=EP0_STATE_GD_STR_I1; 
				    	    	break; 
			    		case 2:	 
				    	    	ep0State=EP0_STATE_GD_STR_I2; 
				    	    	break; 
			    		default: 
				    		//DbgPrintf("[UE:STRI?]"); 
				    		break; 
			    	}//End of SW3 
		    		ep0SubState=0; 
		    		break; 
			case INTERFACE_TYPE: 
	 	    		//DbgPrintf("[GDI]"); 
	 	    		#ifndef _FOR_UDISK_ 
	 	    			CLR_EP0_OUT_PKT_RDY(); 
				#endif 
		    		ep0State=EP0_STATE_GD_IF_ONLY_0; //for WIN98 
		    		break; 
			case ENDPOINT_TYPE:	    	 
	 	    		//DbgPrintf("[GDE]"); 
	 	    		#ifndef _FOR_UDISK_ 
	 	    			CLR_EP0_OUT_PKT_RDY(); 
				#endif 
	 	    		switch(descSetup.bValueL&0xf)//SW4 
		    		{ 
		    		case 0: 
		    			ep0State=EP0_STATE_GD_EP0_ONLY_0; 
		    			break; 
		    		case 1: 
	       	    		ep0State=EP0_STATE_GD_EP1_ONLY_0; 
		    			break; 
		    		default: 
		    			//DbgPrintf("[UE:GDE?]"); 
		    			break; 
		    		}//End of SW4 
		    		break; 
			default: 
		    		//DbgPrintf("[UE:GD?]"); 
		    		break; 
		}//End of SW2	 
    		break; 
 
    	case SET_ADDRESS: 
            //DbgPrintf("[SA:%d]",descSetup.bValueL); 
#ifdef _FOR_UDISK_ 
		if(USBD_flg==1) 
		   	WrPktEp0(0,0); 
#endif 
            	rFUNC_ADDR_REG=descSetup.bValueL | 0x80; 
		CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. 
            	ep0State=EP0_STATE_INIT; 
            break; 
     
	case SET_CONFIGURATION: 
            //DbgPrintf("[SC]"); 
#ifdef _FOR_UDISK_ 
		   if(USBD_flg==1) 
		   	WrPktEp0(0,0); 
#endif 
            	CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. 
            	ep0State=EP0_STATE_INIT; 
            	isUsbdSetConfiguration=1;  
	    	break; 
  	default: 
			//DbgPrintf("[UE:SETUP=%x]",descSetup.bRequest); 
    	    	CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers. 
	    	ep0State=EP0_STATE_INIT; 
	    	break; 
		}//End of SW1 
    }// 
     
    switch(ep0State) 
    {	 
	case EP0_STATE_INIT: 
		break;  
 
		//=== GET_DESCRIPTOR:DEVICE === 
		// Send USB device descriptor to USB host, total 18 bytes. 
    	case EP0_STATE_GD_DEV_0: 
	        //DbgPrintf("[GDD0]"); 
	        //Uart_Printf("start of USB_DEVICE_DESCRIPTOR\n"); 
	        WrPktEp0((U8 *)&descDev+0x00,8); 
			//Write 8 bytes data (0-7) of USB_DEVICE_DESCRIPTOR into EP0_FIFO 
	        SET_EP0_IN_PKT_RDY(); 
	        ep0State=EP0_STATE_GD_DEV_1; 
	        break; 
         
    	case EP0_STATE_GD_DEV_1: 
	        //DbgPrintf("[GDD1]"); 
	        WrPktEp0((U8 *)&descDev+0x08,8); 
			//Write 8 bytes data (8-15) of USB_DEVICE_DESCRIPTOR into EP0_FIFO 
	        SET_EP0_IN_PKT_RDY(); 
	        ep0State=EP0_STATE_GD_DEV_2; 
	        break; 
 
    	case EP0_STATE_GD_DEV_2: 
	        //DbgPrintf("[GDD2]"); 
	        WrPktEp0((U8 *)&descDev+0x10,2);   //8+8+2=0x12 
			//Write 2 bytes data (16-17) of USB_DEVICE_DESCRIPTOR into EP0_FIFO 
	        SET_EP0_INPKTRDY_DATAEND(); 
	        ep0State=EP0_STATE_INIT; 
		//Uart_Printf("end of USB_DEVICE_DESCRIPTOR\n"); 
	        break; 
 
	    //=== GET_DESCRIPTOR:CONFIGURATION+INTERFACE+ENDPOINT0+ENDPOINT1 === 
	    //Windows98 gets these 4 descriptors all together by issuing only a request. 
	    //Windows2000 gets each descriptor seperately. 
    	case EP0_STATE_GD_CFG_0: 
	        //DbgPrintf("[GDC0]"); 
	        WrPktEp0((U8 *)&descConf+0x00,8); //EP0_PKT_SIZE 
	        SET_EP0_IN_PKT_RDY(); 
	        ep0State=EP0_STATE_GD_CFG_1; 
	        break; 
     
    	case EP0_STATE_GD_CFG_1: 
	        //DbgPrintf("[GDC1]"); 
	        WrPktEp0((U8 *)&descConf+0x08,1);  
	        WrPktEp0((U8 *)&descIf+0x00,7);  
	        SET_EP0_IN_PKT_RDY(); 
	        ep0State=EP0_STATE_GD_CFG_2; 
	        break; 
 
    	case EP0_STATE_GD_CFG_2: 
	        //DbgPrintf("[GDC2]"); 
	        WrPktEp0((U8 *)&descIf+0x07,2);  
	        WrPktEp0((U8 *)&descEndpt0+0x00,6);  
	        SET_EP0_IN_PKT_RDY(); 
	        ep0State=EP0_STATE_GD_CFG_3; 
	        break; 
 
    	case EP0_STATE_GD_CFG_3: 
	        //DbgPrintf("[GDC3]"); 
	        WrPktEp0((U8 *)&descEndpt0+0x06,1);  
	        WrPktEp0((U8 *)&descEndpt1+0x00,7);  
	        SET_EP0_IN_PKT_RDY(); 
	        ep0State=EP0_STATE_GD_CFG_4;             
	        break; 
 
    	case EP0_STATE_GD_CFG_4: 
	        //DbgPrintf("[GDC4]"); 
	        //zero length data packit  
	        SET_EP0_INPKTRDY_DATAEND(); 
	        ep0State=EP0_STATE_INIT;             
	        break; 
 
	    //=== GET_DESCRIPTOR:CONFIGURATION ONLY , For Win2K only === 
		// Send USB configuration descriptor to USB host, total 9 bytes. 
    	case EP0_STATE_GD_CFG_ONLY_0: 
	        //DbgPrintf("[GDCO0]"); 
	        WrPktEp0((U8 *)&descConf+0x00,8); //EP0_PKT_SIZE 
	        SET_EP0_IN_PKT_RDY(); 
	        ep0State=EP0_STATE_GD_CFG_ONLY_1; 
	        break; 
 
    	case EP0_STATE_GD_CFG_ONLY_1: 
	        //DbgPrintf("[GDCO1]"); 
	        WrPktEp0((U8 *)&descConf+0x08,1);  
	        SET_EP0_INPKTRDY_DATAEND(); 
	        ep0State=EP0_STATE_INIT;             
	        break; 
 
	    //=== GET_DESCRIPTOR:INTERFACE ONLY=== 
		// Send USB interface descriptor to USB host, total 9 bytes. 
    	case EP0_STATE_GD_IF_ONLY_0: 
	        //DbgPrintf("[GDI0]"); 
	        WrPktEp0((U8 *)&descIf+0,8);  
	        SET_EP0_IN_PKT_RDY(); 
	        ep0State=EP0_STATE_GD_IF_ONLY_1; 
	        break; 
	    	case EP0_STATE_GD_IF_ONLY_1: 
	        //DbgPrintf("[GDI1]"); 
	        WrPktEp0((U8 *)&descIf+8,1);  
	        SET_EP0_INPKTRDY_DATAEND(); 
	        ep0State=EP0_STATE_INIT;             
	        break; 
 
	    //=== GET_DESCRIPTOR:ENDPOINT 0 ONLY=== 
		// Send USB ENDPOINT_0 descriptor to USB host, total 7 bytes. 
    	case EP0_STATE_GD_EP0_ONLY_0: 
	        //DbgPrintf("[GDE00]"); 
	        WrPktEp0((U8 *)&descEndpt0+0,7);  
	        SET_EP0_INPKTRDY_DATAEND(); 
	        ep0State=EP0_STATE_INIT;             
	        break; 
	         
	    //=== GET_DESCRIPTOR:ENDPOINT 1 ONLY=== 
		// Send USB ENDPOINT_1 descriptor to USB host, total 7 bytes. 
    	case EP0_STATE_GD_EP1_ONLY_0: 
	        //DbgPrintf("[GDE10]"); 
	        WrPktEp0((U8 *)&descEndpt1+0,7);  
	        SET_EP0_INPKTRDY_DATAEND(); 
	        ep0State=EP0_STATE_INIT;             
	        break; 
  
    //=== GET_DESCRIPTOR:STRING === 
    	case EP0_STATE_GD_STR_I0: 
        //DbgPrintf("[GDS0_0]"); 
#ifdef _FOR_UDISK_ 
		if(USBD_flg==1) 
		{ 
		   	if(descSetup.bLengthL+(descSetup.bLengthH<<8) <4) 
				WrPktEp0((U8 *)descStr0, /*4*/descSetup.bLengthL+(descSetup.bLengthH<<8) ); 	 
			else 
				SET_EP0_INPKTRDY_DATAEND(); 
		} 
		else if(USBD_flg==0) 
		{ 
			WrPktEp0((U8 *)descStr0, 4 );   
			SET_EP0_INPKTRDY_DATAEND(); 
		} 
#else 
		WrPktEp0((U8 *)descStr0, 4 );   
		SET_EP0_INPKTRDY_DATAEND(); 
#endif 
		ep0State=EP0_STATE_INIT;      
		ep0SubState=0; 
		break; 
 
	case EP0_STATE_GD_STR_I1: 
        //DbgPrintf("[GDS1_%d]",ep0SubState); 
#ifndef _FOR_UDISK_ 
	        if((ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE) < sizeof(descStr1)) 
	        { 
	            WrPktEp0((U8 *)descStr1+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE);  
	            SET_EP0_IN_PKT_RDY(); 
	            ep0State=EP0_STATE_GD_STR_I1; 
	            ep0SubState++; 
	        } 
		else 
		{ 
	    	WrPktEp0((U8 *)descStr1+(ep0SubState*EP0_PKT_SIZE), 
	    	 sizeof(descStr1)-(ep0SubState*EP0_PKT_SIZE));  
			SET_EP0_INPKTRDY_DATAEND(); 
			ep0State=EP0_STATE_INIT;      
			ep0SubState=0; 
		} 
#else 
		if(USBD_flg==1) 
		{ 
			while(1) 
			{ 
		        //Uart_Printf("[GDS1_%d]",ep0SubState); 
			       if(descSetup.bLengthL+(descSetup.bLengthH<<8) +++ 
    descConf.wTotalLengthH=0; 
    descConf.bNumInterfaces=1; 
	//dbg    descConf.bConfigurationValue=2;  //why 2? There's no reason. 
    descConf.bConfigurationValue=1;   
    descConf.iConfiguration=0; 
    descConf.bmAttributes=CONF_ATTR_DEFAULT;//bus powered only. 
    descConf.maxPower=25; //draws 50mA current from the USB bus.           
 
    //Standard interface descriptor 
    descIf.bLength=0x9;     
    descIf.bDescriptorType=INTERFACE_TYPE;//0x04          
    descIf.bInterfaceNumber=0x0; 
    descIf.bAlternateSetting=0x0; //? 
    descIf.bNumEndpoints=2;	//# of endpoints except EP0 
    descIf.bInterfaceClass=0xff; //0x0 ? 
    descIf.bInterfaceSubClass=0x0;   
    descIf.bInterfaceProtocol=0x0; 
    descIf.iInterface=0x0; 
 
    //Standard endpoint0 descriptor 
    descEndpt0.bLength=0x7;     
    descEndpt0.bDescriptorType=ENDPOINT_TYPE;//0x05          
    descEndpt0.bEndpointAddress=1|EP_ADDR_IN;//0x80|0x01=0x81   // 2400Xendpoint 1 is IN endpoint. 
    descEndpt0.bmAttributes=EP_ATTR_BULK;//0x02,transmition type = Bulk 
    descEndpt0.wMaxPacketSizeL=EP1_PKT_SIZE; //64 
    descEndpt0.wMaxPacketSizeH=0x0; 
    descEndpt0.bInterval=0x0; //not used 
 
    //Standard endpoint1 descriptor 
    descEndpt1.bLength=0x7;     
    descEndpt1.bDescriptorType=ENDPOINT_TYPE;//0x05          
    descEndpt1.bEndpointAddress=3|EP_ADDR_OUT;//0x00|0x03=0x03   // 2400X endpoint 3 is OUT endpoint. 
    descEndpt1.bmAttributes=EP_ATTR_BULK;//0x02,transmition type = Bulk 
    descEndpt1.wMaxPacketSizeL=EP3_PKT_SIZE; //64 
    descEndpt1.wMaxPacketSizeH=0x0; 
    descEndpt1.bInterval=0x0; //not used  
#else 
	if(USBD_flg==1) 
	{ 
		//Uart_Printf("InitDescriptorTable()\n"); 
		//Standard device descriptor 
	    descDev.bLength=0x12;//EP0_DEV_DESC_SIZE=0x12 bytes     
	    descDev.bDescriptorType=DEVICE_TYPE;          
	    descDev.bcdUSBL=0x10; 
	    descDev.bcdUSBH=0x01;//Indicate USB Ver 1.10 
	    descDev.bDeviceClass=0x00;//Vendor specific 
	    descDev.bDeviceSubClass=0x0;           
	    descDev.bDeviceProtocol=0x0;//?? should be 0xff           
	    descDev.bMaxPacketSize0=0x8;//EndPoint_0's max Packet Size          
	    descDev.idVendorL=0x71;//0x40;//Vendor ID_h 
	    descDev.idVendorH=0x11;//0x52;//Vendor ID_l 
	    descDev.idProductL=0xf0;//0x03;//Product ID_h 
	    descDev.idProductH=0xff;//0x04;//Product ID_l 
	    descDev.bcdDeviceL=0x00;//Product version_h 
	    descDev.bcdDeviceH=0x01;//Product version_l 
	    descDev.iManufacturer=0x1;//index of string descriptor index 
	    descDev.iProduct=0x2;//index of string descriptor index 
	    descDev.iSerialNumber=0x0;//Product serial number string descriptor index 
	    descDev.bNumConfigurations=0x1;//Device descriptor number 
 
	    //Standard configuration descriptor 
	    descConf.bLength=0x09;     
	    descConf.bDescriptorType=CONFIGURATION_TYPE;//0x02 
	    descConf.wTotalLengthL=0x20; //+++ 
	    descConf.wTotalLengthH=0; 
	    descConf.bNumInterfaces=1; 
		//dbg    descConf.bConfigurationValue=2;  //why 2? There's no reason. 
	    descConf.bConfigurationValue=1;   
	    descConf.iConfiguration=0; 
	    descConf.bmAttributes=CONF_ATTR_DEFAULT;//0x0a;//bus powered only. 
	    descConf.maxPower=0x32;//25; //draws 50mA current from the USB bus.           
 
	    //Standard interface descriptor 
	    descIf.bLength=0x9;     
	    descIf.bDescriptorType=INTERFACE_TYPE;//0x04          
	    descIf.bInterfaceNumber=0x0; 
	    descIf.bAlternateSetting=0x0; //? 
	    descIf.bNumEndpoints=2;	//# of endpoints except EP0 
	    descIf.bInterfaceClass=0x08; //0x0 ? 
	    descIf.bInterfaceSubClass=0x06;//0x04;//0x04:软盘,oxo6:普通邋邋SCSI 
	    descIf.bInterfaceProtocol=0x50; 
	    descIf.iInterface=0x0; 
 
	    //Standard endpoint1 descriptor(IN) 
	    descEndpt0.bLength=0x7;     
	    descEndpt0.bDescriptorType=ENDPOINT_TYPE;//0x05          
	    descEndpt0.bEndpointAddress=1|EP_ADDR_IN;//0x80|0x01=0x81   // 2400Xendpoint 1 is IN endpoint. 
	    descEndpt0.bmAttributes=EP_ATTR_BULK;//0x02,transmition type = Bulk 
	    descEndpt0.wMaxPacketSizeL=EP1_PKT_SIZE; //64 
	    descEndpt0.wMaxPacketSizeH=0x0; 
	    descEndpt0.bInterval=0x0; //not used 
 
	    //Standard endpoint3 descriptor(OUT) 
	    descEndpt1.bLength=0x7;     
	    descEndpt1.bDescriptorType=ENDPOINT_TYPE;//0x05          
	    descEndpt1.bEndpointAddress=3|EP_ADDR_OUT;//0x00|0x03=0x03   // 2400X endpoint 3 is OUT endpoint. 
	    descEndpt1.bmAttributes=EP_ATTR_BULK;//0x02,transmition type = Bulk 
	    descEndpt1.wMaxPacketSizeL=EP3_PKT_SIZE; //64 
	    descEndpt1.wMaxPacketSizeH=0x0; 
	    descEndpt1.bInterval=0x0; //not used  
	} 
	else if(USBD_flg==0) 
	{ 
	    //Standard device descriptor 
	    descDev.bLength=0x12;//EP0_DEV_DESC_SIZE=0x12 bytes     
	    descDev.bDescriptorType=DEVICE_TYPE;          
	    descDev.bcdUSBL=0x10; 
	    descDev.bcdUSBH=0x01;//Indicate USB Ver 1.10 
	    descDev.bDeviceClass=0xFF;//Vendor specific 
	    descDev.bDeviceSubClass=0x0;           
	    descDev.bDeviceProtocol=0x0;//?? should be 0xff           
	    descDev.bMaxPacketSize0=0x8;//EndPoint_0's max Packet Size          
	    descDev.idVendorL=0x45;//Vendor ID_h 
	    descDev.idVendorH=0x53;//Vendor ID_l 
	    descDev.idProductL=0x34;//Product ID_h 
	    descDev.idProductH=0x12;//Product ID_l 
	    descDev.bcdDeviceL=0x00;//Product version_h 
	    descDev.bcdDeviceH=0x01;//Product version_l 
	    descDev.iManufacturer=0x1;//index of string descriptor index 
	    descDev.iProduct=0x2;//index of string descriptor index 
	    descDev.iSerialNumber=0x0;//Product serial number string descriptor index 
	    descDev.bNumConfigurations=0x1;//Device descriptor number 
 
	    //Standard configuration descriptor 
	    descConf.bLength=0x09;     
	    descConf.bDescriptorType=CONFIGURATION_TYPE;//0x02 
	    descConf.wTotalLengthL=0x20; //+++ 
	    descConf.wTotalLengthH=0; 
	    descConf.bNumInterfaces=1; 
		//dbg    descConf.bConfigurationValue=2;  //why 2? There's no reason. 
	    descConf.bConfigurationValue=1;   
	    descConf.iConfiguration=0; 
	    descConf.bmAttributes=CONF_ATTR_DEFAULT;//bus powered only. 
	    descConf.maxPower=25; //draws 50mA current from the USB bus.           
 
	    //Standard interface descriptor 
	    descIf.bLength=0x9;     
	    descIf.bDescriptorType=INTERFACE_TYPE;//0x04          
	    descIf.bInterfaceNumber=0x0; 
	    descIf.bAlternateSetting=0x0; //? 
	    descIf.bNumEndpoints=2;	//# of endpoints except EP0 
	    descIf.bInterfaceClass=0xff; //0x0 ? 
	    descIf.bInterfaceSubClass=0x0;   
	    descIf.bInterfaceProtocol=0x0; 
	    descIf.iInterface=0x0; 
 
	    //Standard endpoint0 descriptor 
	    descEndpt0.bLength=0x7;     
	    descEndpt0.bDescriptorType=ENDPOINT_TYPE;//0x05          
	    descEndpt0.bEndpointAddress=1|EP_ADDR_IN;//0x80|0x01=0x81   // 2400Xendpoint 1 is IN endpoint. 
	    descEndpt0.bmAttributes=EP_ATTR_BULK;//0x02,transmition type = Bulk 
	    descEndpt0.wMaxPacketSizeL=EP1_PKT_SIZE; //64 
	    descEndpt0.wMaxPacketSizeH=0x0; 
	    descEndpt0.bInterval=0x0; //not used 
 
	    //Standard endpoint1 descriptor 
	    descEndpt1.bLength=0x7;     
	    descEndpt1.bDescriptorType=ENDPOINT_TYPE;//0x05          
	    descEndpt1.bEndpointAddress=3|EP_ADDR_OUT;//0x00|0x03=0x03   // 2400X endpoint 3 is OUT endpoint. 
	    descEndpt1.bmAttributes=EP_ATTR_BULK;//0x02,transmition type = Bulk 
	    descEndpt1.wMaxPacketSizeL=EP3_PKT_SIZE; //64 
	    descEndpt1.wMaxPacketSizeH=0x0; 
	    descEndpt1.bInterval=0x0; //not used 	 
	} 
#endif 
}