Example #1
0
void Ep0Handler(void)
{
    static int ep0SubState;
//    int i;
    u_char ep0_csr;

    rINDEX_REG=0;
    ep0_csr=rEP0_CSR;
    
//    DbgOut("<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)
    {   
    	 // 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.
//   	DbgOut("[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;
		return;
    }	

    //I think that EP0_SENT_STALL will not be set to 1.
    if(ep0_csr & EP0_SENT_STALL)
    {   
//		DbgOut("[STALL]");
	   	CLR_EP0_SENT_STALL();
		if(ep0_csr & EP0_OUT_PKT_READY) 
		{
		    CLR_EP0_OUT_PKT_RDY();
		}
	
		ep0State=EP0_STATE_INIT;
		return;
    }

    if((ep0_csr & EP0_OUT_PKT_READY) && (ep0State==EP0_STATE_INIT))
    {	
		RdPktEp0((u_char *)&descSetup,EP0_PKT_SIZE);
    
		switch(descSetup.bRequest)
    	{
    	case GET_DESCRIPTOR:
            switch(descSetup.bValueH)        
            {
            case DEVICE_TYPE:
// 	    		DbgOut("[GDD]");
	 	    	CLR_EP0_OUT_PKT_RDY();
		    	ep0State=EP0_STATE_GD_DEV_0;	        
	    		break;	
	    		
		    case CONFIGURATION_TYPE:
// 			   	DbgOut("[GDC]");
 	    		CLR_EP0_OUT_PKT_RDY();
	 	    	if((descSetup.bLengthL+(descSetup.bLengthH<<8))>0x9)
 	    	  //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:
// 		    	DbgOut("[GDS]");
 	    		CLR_EP0_OUT_PKT_RDY();
	    		switch(descSetup.bValueL)
	    		{
	    	    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:
//	    			DbgOut("[UE:STRI?]");
	    			break;
	    		}
		    	ep0SubState=0;
		    	break;
		    	
	    	case INTERFACE_TYPE:
// 	    		DbgOut("[GDI]");
	 	    	CLR_EP0_OUT_PKT_RDY();
		    	ep0State=EP0_STATE_GD_IF_ONLY_0; //for WIN98
	    		break;
	    		
		    case ENDPOINT_TYPE:	    	
// 		    	DbgOut("[GDE]");
 	    		CLR_EP0_OUT_PKT_RDY();
 	    		switch(descSetup.bValueL&0xf)
		    	{
		    	case 0:
	    		    ep0State=EP0_STATE_GD_EP0_ONLY_0;
	    		    break;
		    	case 1:
					ep0State=EP0_STATE_GD_EP1_ONLY_0;
	    		    break;
	    		default:
//	    	    	DbgOut("[UE:GDE?]");
		    	    break;
		    	}
	    		break;
		    default:
//		    	DbgOut("[UE:GD?]");
	    		break;
		    }	
   		    break;
   		    
    	case SET_ADDRESS:
//			DbgOut("[SA:%d]",descSetup.bValueL);
            rFUNC_ADDR_REG=descSetup.bValueL | 0x80;
		    CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
            ep0State=EP0_STATE_INIT;
            break;    	
            
		case SET_CONFIGURATION:
//			DbgOut("[SC]");
            CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
            ep0State=EP0_STATE_INIT;
            isUSBSet=true; 
    	    break;
    	    
  		default:
//			DbgOut("[UE:SETUP=%x]",descSetup.bRequest);
    	    CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
		    ep0State=EP0_STATE_INIT;
	    	break;    	
        }
    }
    
    switch(ep0State)
    {	
	case EP0_STATE_INIT:
	    break; 

	//=== GET_DESCRIPTOR:DEVICE ===
   	case EP0_STATE_GD_DEV_0:
//		DbgOut("[GDD0]");
		WrPktEp0((u_char *)&descDev+0,8); //EP0_PKT_SIZE
		SET_EP0_IN_PKT_RDY();
		ep0State=EP0_STATE_GD_DEV_1;
		break;
            
	case EP0_STATE_GD_DEV_1:
//		DbgOut("[GDD1]");
		WrPktEp0((u_char *)&descDev+0x8,8); 
		SET_EP0_IN_PKT_RDY();            
		ep0State=EP0_STATE_GD_DEV_2;
		break;

	case EP0_STATE_GD_DEV_2:
//		DbgOut("[GDD2]");
		WrPktEp0((u_char *)&descDev+0x10,2);   //8+8+2=0x12
		SET_EP0_INPKTRDY_DATAEND();
		ep0State=EP0_STATE_INIT;
		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:
//		DbgOut("[GDC0]");
		WrPktEp0((u_char *)&descConf+0,8); //EP0_PKT_SIZE
		SET_EP0_IN_PKT_RDY();
		ep0State=EP0_STATE_GD_CFG_1;
		break;
    
	case EP0_STATE_GD_CFG_1:
//		DbgOut("[GDC1]");
		WrPktEp0((u_char *)&descConf+8,1); 
		WrPktEp0((u_char *)&descIf+0,7); 
		SET_EP0_IN_PKT_RDY();
        ep0State=EP0_STATE_GD_CFG_2;
        break;

  	case EP0_STATE_GD_CFG_2:
//		DbgOut("[GDC2]");
        WrPktEp0((u_char *)&descIf+7,2); 
        WrPktEp0((u_char *)&descEndpt0+0,6); 
        SET_EP0_IN_PKT_RDY();
        ep0State=EP0_STATE_GD_CFG_3;
        break;

   	case EP0_STATE_GD_CFG_3:
//		DbgOut("[GDC3]");
        WrPktEp0((u_char *)&descEndpt0+6,1); 
        WrPktEp0((u_char *)&descEndpt1+0,7); 
        SET_EP0_IN_PKT_RDY();
        ep0State=EP0_STATE_GD_CFG_4;            
        break;

   	case EP0_STATE_GD_CFG_4:
//		DbgOut("[GDC4]");
		//zero length data packit 
		SET_EP0_INPKTRDY_DATAEND();
		ep0State=EP0_STATE_INIT;            
        break;

    //=== GET_DESCRIPTOR:CONFIGURATION ONLY===
   	case EP0_STATE_GD_CFG_ONLY_0:
//		DbgOut("[GDCO0]");
        WrPktEp0((u_char *)&descConf+0,8); //EP0_PKT_SIZE
        SET_EP0_IN_PKT_RDY();
        ep0State=EP0_STATE_GD_CFG_ONLY_1;
        break;
    
	case EP0_STATE_GD_CFG_ONLY_1:
//		DbgOut("[GDCO1]");
        WrPktEp0((u_char *)&descConf+8,1); 
        SET_EP0_INPKTRDY_DATAEND();
        ep0State=EP0_STATE_INIT;            
        break;

    //=== GET_DESCRIPTOR:INTERFACE ONLY===
   	case EP0_STATE_GD_IF_ONLY_0:
//		DbgOut("[GDI0]");
        WrPktEp0((u_char *)&descIf+0,8); 
        SET_EP0_IN_PKT_RDY();
        ep0State=EP0_STATE_GD_IF_ONLY_1;
        break;
        
   	case EP0_STATE_GD_IF_ONLY_1:
//		DbgOut("[GDI1]");
        WrPktEp0((u_char *)&descIf+8,1); 
        SET_EP0_INPKTRDY_DATAEND();
        ep0State=EP0_STATE_INIT;            
        break;

    //=== GET_DESCRIPTOR:ENDPOINT 0 ONLY===
   	case EP0_STATE_GD_EP0_ONLY_0:
//		DbgOut("[GDE00]");
        WrPktEp0((u_char *)&descEndpt0+0,7); 
        SET_EP0_INPKTRDY_DATAEND();
        ep0State=EP0_STATE_INIT;            
        break;
            
    //=== GET_DESCRIPTOR:ENDPOINT 1 ONLY===
   	case EP0_STATE_GD_EP1_ONLY_0:
//		DbgOut("[GDE10]");
        WrPktEp0((u_char *)&descEndpt1+0,7); 
        SET_EP0_INPKTRDY_DATAEND();
        ep0State=EP0_STATE_INIT;            
        break;
 
    //=== GET_DESCRIPTOR:STRING ===
   	case EP0_STATE_GD_STR_I0:
//		DbgOut("[GDS0_0]");
	    WrPktEp0((u_char *)descStr0, 4 );  
	    SET_EP0_INPKTRDY_DATAEND();
	    ep0State=EP0_STATE_INIT;     
	    ep0SubState=0;
	    break;

	case EP0_STATE_GD_STR_I1:
//		DbgOut("[GDS1_%d]",ep0SubState);
		if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr1) )
		{
			WrPktEp0((u_char *)descStr1+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_STR_I1;
            ep0SubState++;
		}
	    else
	    {
	    	WrPktEp0((u_char *)descStr1+(ep0SubState*EP0_PKT_SIZE),
	    		 sizeof(descStr1)-(ep0SubState*EP0_PKT_SIZE)); 
			SET_EP0_INPKTRDY_DATAEND();
			ep0State=EP0_STATE_INIT;     
			ep0SubState=0;
	    }
	    break;

	case EP0_STATE_GD_STR_I2:
//		DbgOut("[GDS2_%d]",ep0SubState);
        if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr2) )
        {
        	WrPktEp0((u_char *)descStr2+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_STR_I2;
            ep0SubState++;
		}
	    else
	    {
//			DbgOut("[E]");
	    	WrPktEp0((u_char *)descStr2+(ep0SubState*EP0_PKT_SIZE),
	    		 sizeof(descStr2)-(ep0SubState*EP0_PKT_SIZE)); 
			SET_EP0_INPKTRDY_DATAEND();
			ep0State=EP0_STATE_INIT;     
			ep0SubState=0;
	    }
		break;
		
	default:
//		DbgOut("UE:G?D");
    	break;
    }
}
Example #2
0
void Ep0Handler(void)
{
    static int ep0SubState;
    int i;
    U8 ep0_csr;

    usbdevregs->INDEX_REG=0;
    ep0_csr=usbdevregs->EP0_CSR_IN_CSR1_REG;
    
    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)
    {   
    	 // 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;
	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;
	return;
    }	



    if((ep0_csr & EP0_OUT_PKT_READY)) // && (ep0State==EP0_STATE_INIT))
    {	
	RdPktEp0((U8 *)&descSetup,EP0_PKT_SIZE);

	PrintEp0Pkt((U8 *)(&descSetup)); //DEBUG
    
	switch(descSetup.bRequest)
    	{
    	case GET_DESCRIPTOR:
            switch(descSetup.bValueH)        
            {
            case DEVICE_TYPE:
 	    	DbgPrintf("[GDD]");
 	    	CLR_EP0_OUT_PKT_RDY();
	    	ep0State=EP0_STATE_GD_DEV_0;	        
	    	break;	
	    case CONFIGURATION_TYPE:
 	    	DbgPrintf("[GDC]");
 	    	CLR_EP0_OUT_PKT_RDY();
 	    	if((descSetup.bLengthL+(descSetup.bLengthH<<8))>0x9)
 	    	  //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:
 	    	DbgPrintf("[GDS]");
 	    	CLR_EP0_OUT_PKT_RDY();
	    	switch(descSetup.bValueL)
	    	{
	    	    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;
	    	}
	    	ep0SubState=0;
	    	break;
	    case INTERFACE_TYPE:
 	    	DbgPrintf("[GDI]");
 	    	CLR_EP0_OUT_PKT_RDY();
	    	ep0State=EP0_STATE_GD_IF_ONLY_0; //for WIN98
	    	break;
	    case ENDPOINT_TYPE:	    	
 	    	DbgPrintf("[GDE]");
 	    	CLR_EP0_OUT_PKT_RDY();
 	    	switch(descSetup.bValueL&0xf)
	    	{
	    	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;
	    	}
	    	break;
	    default:
	    	DbgPrintf("[UE:GD?]");
	    	break;
	    }	
    	    break;

    	case SET_ADDRESS:
            DbgPrintf("[SA:%d]",descSetup.bValueL);
            usbdevregs->FUNC_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]");
            ConfigSet.ConfigurationValue=descSetup.bValueL;
            CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
            ep0State=EP0_STATE_INIT;

            isUsbdSetConfiguration=1; 
            break;

    	    //////////////////////// For chapter 9 test ////////////////////

    	  case CLEAR_FEATURE:
    	  	
    	  	switch (descSetup.bmRequestType)
    	  	{
    	  	  case DEVICE_RECIPIENT:
    	  	  	if (descSetup.bValueL == 1)
    	  	  		Rwuen = FALSE;
    	  	  	
    	  	  	break;

    	  	  case ENDPOINT_RECIPIENT:
    	  	  	 if (descSetup.bValueL == 0)
    	  	  	 {
	                       if((descSetup.bIndexL & 0x7f) == 0x00){
	                        StatusGet.Endpoint0= 0;    
	                       }
	                       if((descSetup.bIndexL & 0x8f) == 0x81){           // IN  Endpoint 1
	                         StatusGet.Endpoint1= 0;           
	                        }
	                       if((descSetup.bIndexL & 0x8f) == 0x03){          // OUT Endpoint 3
	                         StatusGet.Endpoint3= 0;      
	                         }
                       }
    	  	  	 
    	  	  	 break;

    	  	  default:
    	  	  	break;
    	  	}
    	  	CLR_EP0_OUTPKTRDY_DATAEND();
    	  	ep0State=EP0_STATE_INIT;
    	  	break;

    	  case GET_CONFIGURATION:

                CLR_EP0_OUT_PKT_RDY();
	    	  ep0State=EP0_CONFIG_SET;
    	  	   
    	         break;


    	  case GET_INTERFACE:
    	  	
    	  	  CLR_EP0_OUT_PKT_RDY();
	    	  ep0State=EP0_INTERFACE_GET;
    	  	  
    	  	  break;

    	  case GET_STATUS:

    	  	switch(descSetup.bmRequestType)
    	  	{
    	  	      case  (0x80):

    	  	 		CLR_EP0_OUT_PKT_RDY();
    	  	 		StatusGet.Device=((U8)Rwuen<<1)|(U8)Selfpwr;
    	  	 		ep0State=EP0_GET_STATUS0;
    	  	 		    	  	 		
                          break;

                     case  (0x81):
                           	CLR_EP0_OUT_PKT_RDY();
    	  	 		StatusGet.Interface=0;
    	  	 		ep0State=EP0_GET_STATUS1;
                          break;

                     case  (0x82):

                     	CLR_EP0_OUT_PKT_RDY();
    	  	 		if((descSetup.bIndexL & 0x7f) == 0x00){
	                          ep0State=EP0_GET_STATUS2;
    	  	 		  }
    	  	 		
	                       if((descSetup.bIndexL & 0x8f) == 0x81){
	                          ep0State=EP0_GET_STATUS3;
	                       }
	                       
	                       if((descSetup.bIndexL & 0x8f) == 0x03){
                                ep0State=EP0_GET_STATUS4;
	                       }
                          break;

                      default:
                          	break;
    	  	}
    	  	      
    	  	break;


    	  case SET_DESCRIPTOR:
    	  	       CLR_EP0_OUTPKTRDY_DATAEND();
    	  	       ep0State=EP0_STATE_INIT;
    	  	break;


    	  case SET_FEATURE:
    	  	 
    	  	switch (descSetup.bmRequestType)
    	  	{
    	  	  case DEVICE_RECIPIENT:
    	  	  	if (descSetup.bValueL == 1)
    	  	  		Rwuen = TRUE;
    	  	  	
    	  	  	break;

    	  	  case ENDPOINT_RECIPIENT:
    	  	  	 if (descSetup.bValueL == 0)
    	  	  	 {
	                       if((descSetup.bIndexL & 0x7f) == 0x00){
	                        StatusGet.Endpoint0= 1;
	                       }
	                       if((descSetup.bIndexL & 0x8f) == 0x81){
	                         StatusGet.Endpoint1= 1;
	                       }
	                       if((descSetup.bIndexL & 0x8f) == 0x03){
	                         StatusGet.Endpoint3= 1;
	                       }
                       }
    	  	  	break;

    	  	  default:
    	  	  	break;
    	  	}
    	  	CLR_EP0_OUTPKTRDY_DATAEND();
    	  	ep0State=EP0_STATE_INIT;
    	  
    	  	break;


    	  case SET_INTERFACE:
    	  	   InterfaceGet.AlternateSetting= descSetup.bValueL;
    	  	   CLR_EP0_OUTPKTRDY_DATAEND(); 
                 ep0State=EP0_STATE_INIT;
    	  	break;

    	  case SYNCH_FRAME:
    	  	ep0State=EP0_STATE_INIT;
    	  	break;

    	  //////////////////////////////////////////////////////////////

  	default:
	    DbgPrintf("[UE:SETUP=%x]",descSetup.bRequest);
    	    CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
	    ep0State=EP0_STATE_INIT;
	    break;
    
        }
    }
    
    switch(ep0State)
    {	
	case EP0_STATE_INIT:
	    break; 

	//=== GET_DESCRIPTOR:DEVICE ===
    	case EP0_STATE_GD_DEV_0:
            DbgPrintf("[GDD0]");
            WrPktEp0((U8 *)&descDev+0,8); //EP0_PKT_SIZE
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_DEV_1;
            break;
            
    	case EP0_STATE_GD_DEV_1:
            DbgPrintf("[GDD1]");
            WrPktEp0((U8 *)&descDev+0x8,8); 
            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
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;
            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+0,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+8,1); 
            WrPktEp0((U8 *)&descIf+0,7); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_2;
            break;

    	case EP0_STATE_GD_CFG_2:
            DbgPrintf("[GDC2]");
            WrPktEp0((U8 *)&descIf+7,2); 
            WrPktEp0((U8 *)&descEndpt0+0,6); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_3;
            break;

    	case EP0_STATE_GD_CFG_3:
            DbgPrintf("[GDC3]");
            WrPktEp0((U8 *)&descEndpt0+6,1); 
            WrPktEp0((U8 *)&descEndpt1+0,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===
    	case EP0_STATE_GD_CFG_ONLY_0:
            DbgPrintf("[GDCO0]");
            WrPktEp0((U8 *)&descConf+0,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+8,1); 
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;            
            break;

        //=== GET_DESCRIPTOR:INTERFACE ONLY===
    	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===
    	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===
    	case EP0_STATE_GD_EP1_ONLY_0:
            DbgPrintf("[GDE10]");
            WrPktEp0((U8 *)&descEndpt1+0,7); 
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;            
            break;
            
////////////////////////////////////////////

         case EP0_INTERFACE_GET:
            WrPktEp0((U8 *)&InterfaceGet+0,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

 
        //=== GET_DESCRIPTOR:STRING ===

    	case EP0_STATE_GD_STR_I0:
            DbgPrintf("[GDS0_0]");
           WrPktEp0((U8 *)descStr0, 4 );  
	    SET_EP0_INPKTRDY_DATAEND();
	    ep0State=EP0_STATE_INIT;     
	    ep0SubState=0;
	    break;

	case EP0_STATE_GD_STR_I1:
            DbgPrintf("[GDS1_%d]",ep0SubState);
             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;
	    }
	    break;

	case EP0_STATE_GD_STR_I2:
            DbgPrintf("[GDS2_%d]",ep0SubState);
             if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr2) )
            {
            	WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); 
            	SET_EP0_IN_PKT_RDY();
            	ep0State=EP0_STATE_GD_STR_I2;
            	ep0SubState++;
            }
	    else
	    {
                DbgPrintf("[E]");
	    	WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE),
	    		 sizeof(descStr2)-(ep0SubState*EP0_PKT_SIZE)); 
		SET_EP0_INPKTRDY_DATAEND();
		ep0State=EP0_STATE_INIT;     
		ep0SubState=0;
	    }
	    break;

	 case EP0_CONFIG_SET:
	 	WrPktEp0((U8 *)&ConfigSet+0,1); 
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
            break;

        case EP0_GET_STATUS0:
	     WrPktEp0((U8 *)&StatusGet+0,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         case EP0_GET_STATUS1:
	     WrPktEp0((U8 *)&StatusGet+1,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         case EP0_GET_STATUS2:
	     WrPktEp0((U8 *)&StatusGet+2,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         case EP0_GET_STATUS3:
	     WrPktEp0((U8 *)&StatusGet+3,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         case EP0_GET_STATUS4:
	     WrPktEp0((U8 *)&StatusGet+4,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         
	 	
     	default:
	    DbgPrintf("UE:G?D");

     	    break;
    }
}
void Ep0Handler(void)
{
    static int ep0SubState;
    int i;
    U8 ep0_csr;
	//U8 in_csr1;
    rINDEX_REG=0;
    ep0_csr=rEP0_CSR;
    
    //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)
    {   
    	 //Uart_Printf("EP0_SETUP_END\n");
    	 // 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) 
	{
		//Uart_Printf("EP0_OUT_PKT_READY\n");
	    FLUSH_EP0_FIFO(); //(???)
	    	//I think this isn't needed because EP0 flush is done automatically.   
	    CLR_EP0_OUT_PKT_RDY();
	}
	
	ep0State=EP0_STATE_INIT;
	return;
    }	

    //I think that EP0_SENT_STALL will not be set to 1.
    if(ep0_csr & EP0_SENT_STALL)
    {   
   	//Uart_Printf("EP0_SENT_STALL\n");
   	//DbgPrintf("[STALL]");
   	CLR_EP0_SENT_STALL();
	if(ep0_csr & EP0_OUT_PKT_READY) 
	{
	    CLR_EP0_OUT_PKT_RDY();
	}
	
	ep0State=EP0_STATE_INIT;
	return;
    }	



    if((ep0_csr & EP0_OUT_PKT_READY) && (ep0State==EP0_STATE_INIT))
    {	
		RdPktEp0((U8 *)&descSetup,EP0_PKT_SIZE);

		//if((descSetup.bmRequestType != 0xa1) && (descSetup.bmRequestType != 0x21))
		if(descSetup.bmRequestType != 0x21)
		{
			switch(descSetup.bRequest)
			{
				case GET_DESCRIPTOR:  
					switch(descSetup.bValueH)        
					{
						case DEVICE_TYPE:
							Uart_Printf("DEVICE_DESCRIPTOR\n");
							CLR_EP0_OUT_PKT_RDY();
							ep0State=EP0_STATE_GD_DEV_0;	        
						break;	
						
						case CONFIGURATION_TYPE:  	
							Uart_Printf("CONFIGURATION_DESCRIPTOR\n");
							CLR_EP0_OUT_PKT_RDY();
								if((descSetup.bLengthL+(descSetup.bLengthH<<8))>0x9)
									//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:	    	
							Uart_Printf("STRING_TYPE_DESCRIPTOR\n");
							CLR_EP0_OUT_PKT_RDY();
							switch(descSetup.bValueL)
							{
								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;
								case 3:
									ep0State=EP0_STATE_GD_STR_I3;
								break;
								
								default:
								break;
							}
							ep0SubState=0;
						break;	    
						
						case INTERFACE_TYPE:
							Uart_Printf("INTERFACE_DESCRIPTOR\n");
							CLR_EP0_OUT_PKT_RDY();
							ep0State=EP0_STATE_GD_IF_ONLY_0; //for WIN98
						break;
	    
						case ENDPOINT_TYPE:	    	
							Uart_Printf("ENDPOINT_DESCRIPTOR\n");
							CLR_EP0_OUT_PKT_RDY();
							switch(descSetup.bValueL&0xf)
							{
								case 0:
									ep0State=EP0_STATE_GD_EP1_ONLY_0;
								break;
								case 1:
									ep0State=EP0_STATE_GD_EP3_ONLY_0;
								break;
								default:									
								break;
							}
						break;						
						
						case REPORT_TYPE:
							Uart_Printf("GET_REPORT_DESCRIPTOR\n");
							CLR_EP0_OUT_PKT_RDY();
							ep0State=EP0_STATE_REPORT_DESCIRPTOR0;         
						break;
						
						default:
						break;	    
					}	
				break;

				case SET_ADDRESS:
					Uart_Printf("SET_ADDRESS\n");					
					rFUNC_ADDR_REG=descSetup.bValueL | 0x80;
					CLR_EP0_OUTPKTRDY_DATAEND();
					ep0State=EP0_STATE_INIT;
				break;
    	
				case SET_CONFIGURATION:
					Uart_Printf("SET_CONFIGURATION\n");
					ConfigSet.ConfigurationValue=descSetup.bValueL;            
					Uart_Printf("%d\n",ConfigSet.ConfigurationValue);
					CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.										
					ep0State=EP0_STATE_INIT;	
					//isUsbdSetConfiguration=1; 
				break;
/*
    	    //////////////////////// For chapter 9 test ////////////////////

				case CLEAR_FEATURE:
					Uart_Printf("CLEAR_FEATURE\n");
					switch (descSetup.bmRequestType)
					{
						case DEVICE_RECIPIENT:
						if (descSetup.bValueL == 1)
							Rwuen = FALSE;  	  	  	
						break;

						case ENDPOINT_RECIPIENT:
							if (descSetup.bValueL == 0)
							{
							if((descSetup.bIndexL & 0x7f) == 0x00){
								StatusGet.Endpoint0= 0;    
							}
							if((descSetup.bIndexL & 0x8f) == 0x81){           // IN  Endpoint 1
								StatusGet.Endpoint1= 0;           
								}
							if((descSetup.bIndexL & 0x8f) == 0x03){          // OUT Endpoint 3
								StatusGet.Endpoint3= 0;      
								}
						}	  	  	 
						break;

						default:
						break;
					}
				CLR_EP0_OUTPKTRDY_DATAEND();
				ep0State=EP0_STATE_INIT;
			break;

			case GET_CONFIGURATION:
				Uart_Printf("GET_CONFIGURATION\n");
                CLR_EP0_OUT_PKT_RDY();
	    	 	ep0State=EP0_CONFIG_SET;	   
    	    break;

			case GET_INTERFACE:
				Uart_Printf("GET_INTERACE\n");
				CLR_EP0_OUT_PKT_RDY();
				ep0State=EP0_INTERFACE_GET;  	  	  
    	  	break;

			case GET_STATUS:
				Uart_Printf("GET_STATUS\n");
				switch(descSetup.bmRequestType)
				{
					case  (0x80):
						CLR_EP0_OUT_PKT_RDY();
						StatusGet.Device=((U8)Rwuen<<1)|(U8)Selfpwr;
						ep0State=EP0_GET_STATUS0;   	  	 		    	  	 		
                    break;

                    case  (0x81):
                        CLR_EP0_OUT_PKT_RDY();
						StatusGet.Interface=0;
						ep0State=EP0_GET_STATUS1;
                    break;

                    case  (0x82):
                     	CLR_EP0_OUT_PKT_RDY();
						if((descSetup.bIndexL & 0x7f) == 0x00){
	                          ep0State=EP0_GET_STATUS2;
						} 	  	 		
	                    if((descSetup.bIndexL & 0x8f) == 0x81){
	                        ep0State=EP0_GET_STATUS3;
	                    }	                       
	                    if((descSetup.bIndexL & 0x8f) == 0x03){
                            ep0State=EP0_GET_STATUS4;
	                    }
                    break;

                    default:
                    break;
				}    	  	      
    	  	break;


			case SET_DESCRIPTOR:
				Uart_Printf("SET_DESCRIPTOR\n");
				CLR_EP0_OUTPKTRDY_DATAEND();
				ep0State=EP0_STATE_INIT;
    	  	break;

			case SET_FEATURE:
				Uart_Printf("SET_FEARURE\n");
				switch (descSetup.bmRequestType)
				{
					case DEVICE_RECIPIENT:
						if (descSetup.bValueL == 1)
						Rwuen = TRUE;   	  	  	
					break;

					case ENDPOINT_RECIPIENT:
						if (descSetup.bValueL == 0)
						{
	                       if((descSetup.bIndexL & 0x7f) == 0x00){
	                        StatusGet.Endpoint0= 1;
	                       }
	                       if((descSetup.bIndexL & 0x8f) == 0x81){
	                         StatusGet.Endpoint1= 1;
	                       }
	                       if((descSetup.bIndexL & 0x8f) == 0x03){
	                         StatusGet.Endpoint3= 1;
	                       }
                       }
					break;

					default:
					break;
				}
				CLR_EP0_OUTPKTRDY_DATAEND();
				ep0State=EP0_STATE_INIT; 	  
    	  	break;

			case SET_INTERFACE:
				InterfaceGet.AlternateSetting= descSetup.bValueL;
				CLR_EP0_OUTPKTRDY_DATAEND(); 
                ep0State=EP0_STATE_INIT;
    	  	break;

			case SYNCH_FRAME:
				ep0State=EP0_STATE_INIT;
    	  	break;
    	  /////////////////////////////////////////////////////////////
*/
			default:
				CLR_EP0_OUTPKTRDY_DATAEND(); //Because of no data control transfers.
				ep0State=EP0_STATE_INIT;
			break;
			}	
		}
		else
		{
			CLR_EP0_OUT_PKT_RDY();
							//CLR_EP0_SENT_STALL();
							//CLR_EP0_SETUP_END();
			Uart_Printf("HDI_REQUEST\n");
			//if(descSetup.bRequest == 0x0a)
			//{
				//case SET_IDLE:
					//Uart_Printf("ÉèÖÿÕÏÐ\n");
					//WrPktEp0(Buf_Idle,0);
				//break;
			//}
		}
    }

	
	
    switch(ep0State)
    {	
	case EP0_STATE_INIT:
	    break; 

	//------------------------------------GET_DESCRIPTOR:DEVICE-----------------------------
	
    	case EP0_STATE_GD_DEV_0:
            WrPktEp0((U8 *)&descDev+0,8); //EP0_PKT_SIZE
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_DEV_1;
            break;
            
    	case EP0_STATE_GD_DEV_1:
            WrPktEp0((U8 *)&descDev+0x8,8); 
            SET_EP0_IN_PKT_RDY();
            
            ep0State=EP0_STATE_GD_DEV_2;
            break;

    	case EP0_STATE_GD_DEV_2:
            WrPktEp0((U8 *)&descDev+0x10,2);   //8+8+2=0x12
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;
            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:
            WrPktEp0((U8 *)&descConf+0,8); //EP0_PKT_SIZE
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_1;
            break;
    
    	case EP0_STATE_GD_CFG_1:
            WrPktEp0((U8 *)&descConf+8,1); 
            WrPktEp0((U8 *)&descIf+0,7); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_2;
            break;

    	case EP0_STATE_GD_CFG_2:
            WrPktEp0((U8 *)&descIf+7,2); 
            WrPktEp0((U8 *)&descHID+0,6); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_3;
            break;

    	case EP0_STATE_GD_CFG_3:
            WrPktEp0((U8 *)&descHID+6,3); 
            WrPktEp0((U8 *)&descEndpt1+0,5); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_4;            
            break;
            
        case EP0_STATE_GD_CFG_4:
            WrPktEp0((U8 *)&descEndpt1+5,2);
            WrPktEp0((U8 *)&descEndpt3,6); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_5;                   
           // SET_EP0_INPKTRDY_DATAEND();
           // ep0State=EP0_STATE_INIT;            
            break;
            
       case EP0_STATE_GD_CFG_5:
       		WrPktEp0((U8 *)&descEndpt3+5,1);
       		SET_EP0_INPKTRDY_DATAEND();
           	ep0State=EP0_STATE_INIT;            

       break;
/*
        case EP0_STATE_GD_CFG_5:
            //DbgPrintf("[GDC4]");
            WrPktEp0((U8 *)&descEndpt3+6,1);                
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;            
            break;
*/
/*
    	case EP0_STATE_GD_CFG_2:
            DbgPrintf("[GDC2]");
            WrPktEp0((U8 *)&descIf+7,2); 
            WrPktEp0((U8 *)&descEndpt0+0,6); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_3;
            break;

    	case EP0_STATE_GD_CFG_3:
            DbgPrintf("[GDC3]");
            WrPktEp0((U8 *)&descEndpt0+6,1); 
            WrPktEp0((U8 *)&descEndpt1+0,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===
    	case EP0_STATE_GD_CFG_ONLY_0:
            WrPktEp0((U8 *)&descConf+0,8); //EP0_PKT_SIZE
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_CFG_ONLY_1;
            break;
    
    	case EP0_STATE_GD_CFG_ONLY_1:
            WrPktEp0((U8 *)&descConf+8,1); 
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;            
            break;

        //=== GET_DESCRIPTOR:INTERFACE ONLY===
    	case EP0_STATE_GD_IF_ONLY_0:
            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:
            WrPktEp0((U8 *)&descIf+8,1); 
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;            
            break;

        //=== GET_DESCRIPTOR:ENDPOINT 0 ONLY===
    	case EP0_STATE_GD_EP1_ONLY_0:
            WrPktEp0((U8 *)&descEndpt1+0,7); 
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;            
            break;
            
        //=== GET_DESCRIPTOR:ENDPOINT 1 ONLY===
    	case EP0_STATE_GD_EP3_ONLY_0:
            DbgPrintf("[GDE10]");
            WrPktEp0((U8 *)&descEndpt3+0,7); 
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;            
            break;
            
////////////////////////////////////////////

         case EP0_INTERFACE_GET:
            WrPktEp0((U8 *)&InterfaceGet+0,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

 
        //=== GET_DESCRIPTOR:STRING ===

    	case EP0_STATE_GD_STR_I0:
           WrPktEp0((U8 *)descStr0, 4 );  
	    	SET_EP0_INPKTRDY_DATAEND();
	    	ep0State=EP0_STATE_INIT;     
	   		ep0SubState=0;
	    break;

	case EP0_STATE_GD_STR_I1:
            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;
	    }
	    break;

	case EP0_STATE_GD_STR_I2:
         if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr2) )
         {
            WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); 
            SET_EP0_IN_PKT_RDY();
            ep0State=EP0_STATE_GD_STR_I2;
            ep0SubState++;
         }
	    else
	    {
	    	WrPktEp0((U8 *)descStr2+(ep0SubState*EP0_PKT_SIZE),
	    	sizeof(descStr2)-(ep0SubState*EP0_PKT_SIZE)); 
			SET_EP0_INPKTRDY_DATAEND();
			ep0State=EP0_STATE_INIT;     
			ep0SubState=0;
	    }
	    break;

	case EP0_STATE_GD_STR_I3:
            if( (ep0SubState*EP0_PKT_SIZE+EP0_PKT_SIZE)<sizeof(descStr3) )
            {
            	WrPktEp0((U8 *)descStr3+(ep0SubState*EP0_PKT_SIZE),EP0_PKT_SIZE); 
            	SET_EP0_IN_PKT_RDY();
            	ep0State=EP0_STATE_GD_STR_I3;
            	ep0SubState++;
            }
	    else
	    {
	    	WrPktEp0((U8 *)descStr3+(ep0SubState*EP0_PKT_SIZE),
	    	sizeof(descStr3)-(ep0SubState*EP0_PKT_SIZE)); 
			SET_EP0_INPKTRDY_DATAEND();
			ep0State=EP0_STATE_INIT;     
			ep0SubState=0;
	    }
	    break;

	 case EP0_CONFIG_SET:
	 	WrPktEp0((U8 *)&ConfigSet+0,1); 
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
            break;

        case EP0_GET_STATUS0:
	     WrPktEp0((U8 *)&StatusGet+0,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         case EP0_GET_STATUS1:
	     WrPktEp0((U8 *)&StatusGet+1,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         case EP0_GET_STATUS2:
	     WrPktEp0((U8 *)&StatusGet+2,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         case EP0_GET_STATUS3:
	     WrPktEp0((U8 *)&StatusGet+3,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;

         case EP0_GET_STATUS4:
	     WrPktEp0((U8 *)&StatusGet+4,1);
            SET_EP0_INPKTRDY_DATAEND();
            ep0State=EP0_STATE_INIT;      
         break;
        
         case EP0_STATE_REPORT_DESCIRPTOR0:  
         	if((ep0SubState*8+8) < sizeof(ReportDescriptor))
         	{      	
         		WrPktEp0((U8*)ReportDescriptor+8*ep0SubState,8);
         		SET_EP0_IN_PKT_RDY();
				ep0State=EP0_STATE_REPORT_DESCIRPTOR0;
				ep0SubState++;
			}
			else
			{
				WrPktEp0((U8 *)ReportDescriptor+(ep0SubState*8),sizeof(ReportDescriptor)-(ep0SubState*8)); 
				SET_EP0_INPKTRDY_DATAEND();
				ep0State=EP0_STATE_INIT;
				ep0SubState=0;
			}         
         break;	 	
	 	
  /*       case EP0_STATE_REPORT_DESCIRPTOR1:        	
         	WrPktEp0((U8*)ReportDescriptor+7,8);
         	SET_EP0_IN_PKT_RDY();
         	SET_EP0_INPKTRDY_DATAEND();
			ep0State=EP0_STATE_REPORT_DESCIRPTOR2;         
         break;		 	
*/	 	
     	default:
     	break;  
    }
   
}