Exemple #1
0
void ProcessIO(void)
{   
  
    if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;

    /*if(USBGetDeviceState() == DETACHED_STATE) {
        if(I2CCount > 0) {
            ProcessCmd(OUTPacket);
            I2CCount = 0;
            }
    }
    else*/
    if(!USBHandleBusy(USBGenericOutHandle)) {
        //if( OUTPacket[1] != MASTER_ADDRESS )
        //    I2CRelay(OUTPacket, USBGEN_EP_SIZE);
        //else
            ProcessCmd(OUTPacket);
    USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM, (BYTE*)&OUTPacket, USBGEN_EP_SIZE);
    }

    if(WQI != WQX && !USBHandleBusy(USBGenericInHandle)) {
        USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM, (BYTE*)&INPacket[WQX*USB_RECORD_SIZE], USB_RECORD_SIZE);
        WQX = (WQX+1) & 3;
    }
} //end ProcessIO
Exemple #2
0
static void processCy7c4xxFifo(void)
{
    unsigned char c;
    static unsigned char *cy7c4xx_buf_ptr = InDataPacket;
    static unsigned char len = 0;

    if (cy7c4xxPull(&c) != 0)
        return;

    if (len) {
        *cy7c4xx_buf_ptr = c;
        ++cy7c4xx_buf_ptr;
        --len;

        if (len == 0) {
#if DEBUG
            if (usbfifo_debug_operation.dump_fifo_out == 1) {
                unsigned char l = cy7c4xx_buf_ptr-InDataPacket, i;
                unsigned char b[12];
                putrsUSART("FIFO IN: '");
                for (i=0;i<l;++i) {
                    if (i != 0) {
                        while (BusyUSART());
                        putcUSART(' ');
                    }
                    sprintf(b, "%02x", InDataPacket[i]);
                    putsUSART(b);
                }
                sprintf(b, "' len=%3d\r\n", l);
                putsUSART(b);
            }

            if (usbfifo_debug_operation.fifo_loopback == 1) {
                unsigned char l = cy7c4xx_buf_ptr-InDataPacket, i; /* length of incoming packet _must_ not exceed the length of outgoing */
                fifo9403aPush(l, 1);
                for (i=0;i<l;++i)
                    fifo9403aPush(InDataPacket[i], 1);
            }
#endif

            /* FIXME: use real ping-pong */
            while (USBHandleBusy(UsbInDataHandle)); // should not loop, anyway ...
            UsbInDataHandle = USBGenWrite(USBGEN_DATA_EP_NUM, (BYTE*)&InDataPacket, cy7c4xx_buf_ptr-InDataPacket);
            while (USBHandleBusy(UsbInDataHandle)); // have to wait here as full ping-pong is not implemented
                                                    // and thus we don't want data from FIFO override the data being sent here

            cy7c4xx_buf_ptr = InDataPacket;
        }
    } else {
        len = c;
    }
}
/**********************************************************************************
  Function:
        BYTE getsUSBUSART(char *buffer, BYTE len)
    
  Summary:
    getsUSBUSART copies a string of BYTEs received through USB CDC Bulk OUT
    endpoint to a user's specified location. It is a non-blocking function.
    It does not wait for data if there is no data available. Instead it
    returns '0' to notify the caller that there is no data available.

  Description:
    getsUSBUSART copies a string of BYTEs received through USB CDC Bulk OUT
    endpoint to a user's specified location. It is a non-blocking function.
    It does not wait for data if there is no data available. Instead it
    returns '0' to notify the caller that there is no data available.
    
    Typical Usage:
    <code>
        BYTE numBytes;
        BYTE buffer[64]
    
        numBytes = getsUSBUSART(buffer,sizeof(buffer)); //until the buffer is free.
        if(numBytes \> 0)
        {
            //we received numBytes bytes of data and they are copied into
            //  the "buffer" variable.  We can do something with the data
            //  here.
        }
    </code>
  Conditions:
    Value of input argument 'len' should be smaller than the maximum
    endpoint size responsible for receiving bulk data from USB host for CDC
    class. Input argument 'buffer' should point to a buffer area that is
    bigger or equal to the size specified by 'len'.
  Input:
    buffer -  Pointer to where received BYTEs are to be stored
    len -     The number of BYTEs expected.
                                                                                   
  **********************************************************************************/
BYTE getsUSBUSART(char *buffer, BYTE len)
{
    cdc_rx_len = 0;
    
    if(!USBHandleBusy(CDCDataOutHandle))
    {
        /*
         * Adjust the expected number of BYTEs to equal
         * the actual number of BYTEs received.
         */
        if(len > USBHandleGetLength(CDCDataOutHandle))
            len = USBHandleGetLength(CDCDataOutHandle);
        
        /*
         * Copy data from dual-ram buffer to user's buffer
         */
        for(cdc_rx_len = 0; cdc_rx_len < len; cdc_rx_len++)
            buffer[cdc_rx_len] = cdc_data_rx[cdc_rx_len];

        /*
         * Prepare dual-ram buffer for next OUT transaction
         */

        CDCDataOutHandle = USBRxOnePacket(CDC_DATA_EP,(BYTE*)&cdc_data_rx,sizeof(cdc_data_rx));

    }//end if
    
    return cdc_rx_len;
    
}//end getsUSBUSART
Exemple #4
0
void FlashDoTX(void)
{    
	BYTE SendNow;
    USBMaskInterrupts();

	if (!USBHandleBusy(FlashDataInHandle)) {
		switch (FlashTxState) {
			case FLASH_TX_COMPLETING:
				FlashTxState = FLASH_TX_READY;
				break;
			
			case FLASH_TX_BUSY:
				SendNow = FlashTxLen > sizeof(FlashTxBuffer) ? sizeof(FlashTxBuffer) : FlashTxLen;
				
				FlashTxCBF((BYTE *) &FlashTxBuffer, SendNow);    	  
		    	FlashTxLen -= SendNow;
		        
		        if(FlashTxLen == 0)
		                FlashTxState = FLASH_TX_COMPLETING;

		        FlashDataInHandle = USBTxOnePacket(NAND_TX_EP,(BYTE*)&FlashTxBuffer, SendNow);
				break;
		}
    }

    USBUnmaskInterrupts();
}
void CDCNotificationHandler(void)
{
    //Check the DTS I/O pin and if a state change is detected, notify the 
    //USB host by sending a serial state notification element packet.
    if(UART_DTS == USB_CDC_DSR_ACTIVE_LEVEL) //UART_DTS must be defined to be an I/O pin in the hardware profile to use the DTS feature (ex: "PORTXbits.RXY")
    {
        SerialStateBitmap.bits.DSR = 1;
    }  
    else
    {
        SerialStateBitmap.bits.DSR = 0;
    }        
    
    //If the state has changed, and the endpoint is available, send a packet to
    //notify the hUSB host of the change.
    if((SerialStateBitmap.byte != OldSerialStateBitmap.byte) && (!USBHandleBusy(CDCNotificationInHandle)))
    {
        //Copy the updated value into the USB packet buffer to send.
        SerialStatePacket.SerialState.byte = SerialStateBitmap.byte;
        //We don't need to write to the other bytes in the SerialStatePacket USB
        //buffer, since they don't change and will always be the same as our
        //initialized value.

        //Send the packet over USB to the host.
        CDCNotificationInHandle = USBTransferOnePacket(CDC_COMM_EP, IN_TO_HOST, (BYTE*)&SerialStatePacket, sizeof(SERIAL_STATE_NOTIFICATION));
        
        //Save the old value, so we can detect changes later.
        OldSerialStateBitmap.byte = SerialStateBitmap.byte;
    }    
}//void CDCNotificationHandler(void)    
/********************************************************************
 *	モニタコマンド受信と実行.
 ********************************************************************
 */
void ProcessIO(void)
{
	// 返答パケットが空であること、かつ、
	// 処理対象の受信データがある.
	if((ToPcRdy == 0) && (USBHandleBusy(USBGenericOutHandle)==0) ) {
		//受信データがあれば、受信データを受け取る.
		memcpy64((char*)&PacketFromPC,(char*)OUTPacket);
		//次の読み込みを発行する.
		USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket
							  ,USBGEN_EP_SIZE);

		PacketToPC.raw[0]=Cmd0;		// CMD ECHOBACK
		//コマンドに対応する処理を呼び出す.
		     if(Cmd0==HIDASP_PEEK) 	{cmd_peek();}	// メモリー読み出し.
		else if(Cmd0==HIDASP_POKE) 	{cmd_poke();}	// メモリー書き込み.
		else if(Cmd0==HIDASP_JMP) 	{cmd_exec();}	// 実行.
		else if(Cmd0==HIDASP_TEST) 	{cmd_echo();}	// 接続テスト.
		else if(Cmd0==HIDASP_GET_STRING){cmd_get_string();}
		else if(Cmd0==HIDASP_USER_CMD)  {cmd_user_cmd();}
		else if(Cmd0==HIDASP_SET_MODE)  {cmd_set_mode();}
	}

	// 必要なら、返答パケットをバルク転送(EP1)でホストPCに返却する.
	if( ToPcRdy ) {
		if(!USBHandleBusy(USBGenericInHandle)) {
			memcpy64(INPacket,(char*)&PacketToPC);
			USBGenericInHandle=USBGenWrite(USBGEN_EP_NUM,(BYTE*)INPacket,USBGEN_EP_SIZE);	
			ToPcRdy = 0;

			if(poll_mode!=0) {
				if( USBHandleBusy(USBGenericOutHandle) ) {//コマンドが来ない限り送り続ける.
					make_report();
				}
			}
		}
	}
}
Exemple #7
0
/**************************************************
*				SWARMS Input PRECESSING
* 
*
*
****************************************************/
void ProcessSWARMSInput(void){
	char commandSuccess;
	char SWARMSCommandID;
 
	if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;
	    // this is where I should insert the code for specific control 
    if(!USBHandleBusy(USBGenericOutHandle))		//Check if the endpoint has received any data from the host.
    {   
	    if(! canfitCommandInOutputCommandBuffer(5)){
		    //can't ensure reply -- just drop frame
		    USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
		    	mLED_2_On();
		    	mLED_1_Off()
			return;
		   } 
		   
		SWARMSCommandID = OUTPacket[0];	    
	    if(IS_VALID_COMMAND){
			commandSuccess = writeInputCommand(OUTPacket);
		switch(commandSuccess){
			case fifoBufferStatusGood:
				//report success
				break;
			case fifoBufferStatusFull:
			//abort buffer full
//			mLED_2_Toggle();
				SWARMSMakeCommandSuccess(SWARMSCommandID, FAILURE, NULL); //TODO: ADD FLAGS
			break;
			case fifoBufferStatusBadInputOversize:
			//abort buffer oversize input
				SWARMSMakeCommandSuccess(SWARMSCommandID, FAILURE, NULL); //TODO: ADD FLAGS
			break;
			case fifoBufferStatusBadInput:
			default:
			//notify bad command
				SWARMSMakeCommandSuccess(SWARMSCommandID, FAILURE, NULL); //TODO: ADD FLAGS
			break;	
		}	  
		   
		}else{
			SWARMSMakeCommandSuccess(SWARMSCommandID, FAILURE, NULL); //TODO: ADD FLAGS
		}	
  			 		
	    	USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
	    
	  } 
Exemple #8
0
void FlashDataWrite()
{
	BYTE *pData = (BYTE *) &FlashRxBuffer;
	BYTE len;

	if (gCommandProgress==0) {
		gGlobalStatus = XNANDErase(gCmdArgA << 5);
		gNextBlock = gCmdArgA << 5;
		gWordsLeft = 0x84;
		gBytesWritten = 0;
		XNANDWriteStart();
		gCommandProgress = 1;
	}

	if (USBHandleBusy(FlashDataOutHandle)) 
		return;
	
	len = USBHandleGetLength(FlashDataOutHandle);
	len/= 4;

	while (len) {
		BYTE writeNow = len > gWordsLeft?gWordsLeft:len;

		XNANDWriteProcess(pData, writeNow);
		pData += writeNow*4;
		len -= writeNow;
		gWordsLeft -= writeNow;

		if (gWordsLeft == 0) {
			gGlobalStatus |= XNANDWriteExecute(gNextBlock);
			gNextBlock++;
			gWordsLeft = 0x84;
			XNANDWriteStart();
			gBytesWritten += 0x210;
		}
	}

    FlashDataOutHandle = USBRxOnePacket(NAND_RX_EP,(BYTE*)&FlashRxBuffer,sizeof(FlashRxBuffer));

	if (gBytesWritten == gCmdArgB)
		gCurrentCommand = 0xFF;
}
Exemple #9
0
//------------------------------PMP Handler-------------------------------------
void __ISR(_EXTERNAL_0_VECTOR, IPL6) GetSlaveData(void){
    unsigned char pitch, vel;
    PMPMasterRead();
    pitch = mPMPMasterReadByte();
    
    vel = mPMPMasterReadByte();

    if(!USBHandleBusy(USBTxHandle))
    {
        midiData.Val = 0;   //must set all unused values to 0

        midiData.CableNumber = 0;
        midiData.CodeIndexNumber = MIDI_CIN_NOTE_ON;
        midiData.DATA_0 = 0x90;                     //Note on
        midiData.DATA_1 = pitch + 60;               //pitch
        midiData.DATA_2 = vel;                      //velocity

        USBTxHandle = USBTxOnePacket(MIDI_EP,(BYTE*)&midiData,4);
    }

    mINT0ClearIntFlag();
}
/******************************************************************************
 	Function:
 		void MSDProcessCommandMediaPresent(void)
 		
 	Description:
 		This funtion processes a command received through the MSD
 		class driver
 		
 	PreCondition:
 		None
 		
 	Paramters:
 		None
 	
 	Return Values:
 		BYTE - the current state of the MSDProcessCommand state
 		machine.  The valid values are defined in MSD.h under the 
 		MSDProcessCommand state machine declaration section
 		
 	Remarks:
 		None
 
 *****************************************************************************/	
void MSDProcessCommandMediaPresent(void)
{
    BYTE i; 

    switch(MSDCommandState)
    {
        case MSD_COMMAND_WAIT:
            //copy the received command to the command state machine
            MSDCommandState = gblCBW.CBWCB[0];
            break;
    	case MSD_INQUIRY:
    	{
            //copy the inquiry results from the defined ROM buffer 
            //  into the USB buffer so that it can be transmitted
        	memcpypgm2ram(
        	    (void *)&msd_buffer[0],
        	    (ROM void*)&inq_resp,
        	    sizeof(InquiryResponse)
        	    );
        	msd_csw.dCSWDataResidue=sizeof(InquiryResponse);
        	msd_csw.bCSWStatus=0x00;			// success
        	MSDCommandState = MSD_COMMAND_RESPONSE;
            break;
        }
        case MSD_READ_CAPACITY:
        {
            //If the host asked for the capacity of the device
            DWORD_VAL sectorSize;
            DWORD_VAL capacity;

        	msd_csw.bCSWStatus=0x00;			  // success
            
            //get the information from the physical media
            capacity.Val = LUNReadCapacity();
            sectorSize.Val = LUNReadSectorSize();
            
            //copy the data to the buffer
        	msd_buffer[0]=capacity.v[3];
        	msd_buffer[1]=capacity.v[2];
        	msd_buffer[2]=capacity.v[1];
        	msd_buffer[3]=capacity.v[0];
        	
        	msd_buffer[4]=sectorSize.v[3];
        	msd_buffer[5]=sectorSize.v[2];
        	msd_buffer[6]=sectorSize.v[1];
        	msd_buffer[7]=sectorSize.v[0];
        
        	msd_csw.dCSWDataResidue=0x08;		  // size of response
        	MSDCommandState = MSD_COMMAND_RESPONSE;
            break;
        }
		case MSD_READ_10:
        	if(MSDReadHandler() == MSD_READ10_WAIT)
        	{
			    MSDCommandState = MSD_COMMAND_WAIT;
            }
            break;
    	case MSD_WRITE_10:
        	if(MSDWriteHandler() == MSD_WRITE10_WAIT)
        	{
			    MSDCommandState = MSD_COMMAND_WAIT;
            }
		    break;
        case MSD_REQUEST_SENSE:    
          	for(i=0;i<sizeof(RequestSenseResponse);i++)
          	{
          		msd_buffer[i]=gblSenseData[LUN_INDEX]._byte[i];
            }
          	
            msd_csw.dCSWDataResidue=sizeof(RequestSenseResponse);
          	msd_csw.bCSWStatus=0x0;					// success
          	MSDCommandState = MSD_COMMAND_RESPONSE;
            break;
	    case MSD_MODE_SENSE:
        	msd_buffer[0]=0x02;
        	msd_buffer[1]=0x00;
        	msd_buffer[2]=0x00;
        	msd_buffer[3]=0x00;
        	
        	msd_csw.bCSWStatus=0x0;
        	msd_csw.dCSWDataResidue=0x04;
        	MSDCommandState = MSD_COMMAND_RESPONSE;
    	    break;
		case MSD_PREVENT_ALLOW_MEDIUM_REMOVAL:
            if(LUNMediaDetect())
            {
        		msd_csw.bCSWStatus=0x00;
        		msd_csw.dCSWDataResidue=0x00;
        	}
            else
            {
        		gblSenseData[LUN_INDEX].SenseKey=S_NOT_READY;
        		gblSenseData[LUN_INDEX].ASC=ASC_MEDIUM_NOT_PRESENT;
        		gblSenseData[LUN_INDEX].ASCQ=ASCQ_MEDIUM_NOT_PRESENT;
        		msd_csw.bCSWStatus=0x01;
        	}
			MSDCommandState = MSD_COMMAND_WAIT;
            break;
		case MSD_TEST_UNIT_READY:
            if((gblSenseData[LUN_INDEX].SenseKey==S_UNIT_ATTENTION) && (msd_csw.bCSWStatus==1))
            {
                MSDCommandState = MSD_COMMAND_WAIT;
            }
            else
            {
            	ResetSenseData();
            	msd_csw.dCSWDataResidue=0x00;
    			MSDCommandState = MSD_COMMAND_WAIT;
            }
            break;
		case MSD_VERIFY:
            //Fall through to STOP_START
		case MSD_STOP_START:
        	msd_csw.bCSWStatus=0x0;
        	msd_csw.dCSWDataResidue=0x00;
			MSDCommandState = MSD_COMMAND_WAIT;
            break;
        case MSD_COMMAND_RESPONSE:
            if(USBHandleBusy(USBMSDInHandle) == FALSE)
            {
                USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,(BYTE*)&msd_buffer[0],msd_csw.dCSWDataResidue);
			    MSDCommandState = MSD_COMMAND_WAIT;

        		msd_csw.dCSWDataResidue=0;
            }
            break;
        case MSD_COMMAND_ERROR:
		default:
        	ResetSenseData();
			gblSenseData[LUN_INDEX].SenseKey=S_ILLEGAL_REQUEST;
			gblSenseData[LUN_INDEX].ASC=ASC_INVALID_COMMAND_OPCODE;
			gblSenseData[LUN_INDEX].ASCQ=ASCQ_INVALID_COMMAND_OPCODE;
			msd_csw.bCSWStatus=0x01;
			msd_csw.dCSWDataResidue=0x00;
			MSDCommandState = MSD_COMMAND_RESPONSE;
 		    break;
	} // end switch	
}
/******************************************************************************
 	Function:
 		void MSDProcessCommandMediaAbsent(void)
 		
 	Description:
 		This funtion processes a command received through the MSD
 		class driver
 		
 	PreCondition:
 		None
 		
 	Parameters:
 		None
 	
 	Return Values:
 		BYTE - the current state of the MSDProcessCommand state
 		machine.  The valid values are defined in MSD.h under the 
 		MSDProcessCommand state machine declaration section
 		
 	Remarks:
 		None
 
  *****************************************************************************/	
void MSDProcessCommandMediaAbsent(void)
{
    BYTE i;

    switch(MSDCommandState)
    {
        case MSD_REQUEST_SENSE:
        {
            ResetSenseData();
            gblSenseData[LUN_INDEX].SenseKey=S_NOT_READY;
    		gblSenseData[LUN_INDEX].ASC=ASC_MEDIUM_NOT_PRESENT;
    		gblSenseData[LUN_INDEX].ASCQ=ASCQ_MEDIUM_NOT_PRESENT;

          	for(i=0;i<sizeof(RequestSenseResponse);i++)
          	{
          		msd_buffer[i]=gblSenseData[LUN_INDEX]._byte[i];
            }
          	
            msd_csw.dCSWDataResidue=sizeof(RequestSenseResponse);
          	msd_csw.bCSWStatus=0x0;					// success
          	MSDCommandState = MSD_COMMAND_RESPONSE;
            break;
        } 
        case MSD_PREVENT_ALLOW_MEDIUM_REMOVAL:
        case MSD_TEST_UNIT_READY:
        {
    		msd_csw.bCSWStatus=0x01;
            MSDCommandState = MSD_COMMAND_WAIT;
            break;
        }
        case MSD_INQUIRY:
        {
        	memcpypgm2ram(
        	    (void *)&msd_buffer[0],
        	    (ROM void*)&inq_resp,
        	    sizeof(InquiryResponse)
        	    );
        	msd_csw.dCSWDataResidue=sizeof(InquiryResponse);
        	msd_csw.bCSWStatus=0x00;			// success
        	MSDCommandState = MSD_COMMAND_RESPONSE;
            break;
        }
        case MSD_COMMAND_WAIT:
        {
            MSDCommandState = gblCBW.CBWCB[0];
            break;
        }
        case MSD_COMMAND_RESPONSE:
            if(USBHandleBusy(USBMSDInHandle) == FALSE)
            {
                USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,(BYTE*)&msd_buffer[0],msd_csw.dCSWDataResidue);
			    MSDCommandState = MSD_COMMAND_WAIT;

        		msd_csw.dCSWDataResidue=0;
            }
            break;
        default:
        {
            //Stall MSD endpoint IN
            USBStallEndpoint(MSD_DATA_IN_EP,1);
    		msd_csw.bCSWStatus=0x01;
            MSDCommandState = MSD_COMMAND_WAIT;
            break;
        }
    }
}
BOOL ChipKITUSBHandleBusy(USB_HANDLE handle)
{
	return(USBHandleBusy(handle));
}
/*********************************************************************************
  Function:
        BYTE MSDTasks(void)
    
  Summary:
    This function runs the MSD class state machines and all of its
    sub-systems. This function should be called periodically once the
    device is in the configured state in order to keep the MSD state
    machine going.
  Description:
    This function runs the MSD class state machines and all of its
    sub-systems. This function should be called periodically once the
    device is in the configured state in order to keep the MSD state
    machine going.
    
    Typical Usage:
    <code>
    void main(void)
    {
        USBDeviceInit();
        while(1)
        {
            USBDeviceTasks();
            if((USBGetDeviceState() \< CONFIGURED_STATE) ||
               (USBIsDeviceSuspended() == TRUE))
            {
                //Either the device is not configured or we are suspended
                //  so we don't want to do execute any application code
                continue;   //go back to the top of the while loop
            }
            else
            {
                //Keep the MSD state machine going
                MSDTasks();
    
                //Run application code.
                UserApplication();
            }
        }
    }
    </code>
  Conditions:
    None
  Return Values:
    BYTE -  the current state of the MSD state machine the valid values are
            defined in MSD.h under the MSDTasks state machine declaration section.
            The possible values are the following\:
            * MSD_WAIT
            * MSD_DATA_IN
            * MSD_DATA_OUT
            * MSD_SEND_CSW
  Remarks:
    None                                                                          
  *********************************************************************************/	
BYTE MSDTasks(void)
{
    BYTE i;
    
    switch(MSD_State)
    {
        case MSD_WAIT:
        {
            //If the MSD state machine is waiting for something to happen
            if(!USBHandleBusy(USBMSDOutHandle))
            {
        		//If we received an OUT packet from the host
                //  then copy the data from the buffer to a global
                //  buffer so that we can keep the information but
                //  reuse the buffer
        		gblCBW.dCBWSignature=msd_cbw.dCBWSignature;					
        		gblCBW.dCBWTag=msd_cbw.dCBWTag;
        		gblCBW.dCBWDataTransferLength=msd_cbw.dCBWDataTransferLength;
            	gblCBW.bCBWFlags=msd_cbw.bCBWFlags;
            	gblCBW.bCBWLUN=msd_cbw.bCBWLUN;
        	    gblCBW.bCBWCBLength=msd_cbw.bCBWCBLength;		// 3 MSB are zero

            	for (i=0;i<msd_cbw.bCBWCBLength;i++)
            	{
            		gblCBW.CBWCB[i]=msd_cbw.CBWCB[i];
                }
            		
                gblCBWLength=USBHandleGetLength(USBMSDOutHandle);

        	    //If this CBW is valid?
        		if ((gblCBWLength==MSD_CBW_SIZE)&&(gblCBW.dCBWSignature==0x43425355)) 
            	{
                    //Is this CBW meaningful?	
       				if((gblCBW.bCBWLUN<=0x0f)
               		&&(gblCBW.bCBWCBLength<=0x10)
               		&&(gblCBW.bCBWCBLength>=0x01)
               		&&(gblCBW.bCBWFlags==0x00||gblCBW.bCBWFlags==0x80)) 
            		{
                		//Prepare the CSW to be sent
                    	msd_csw.dCSWTag=gblCBW.dCBWTag;
                    	msd_csw.dCSWSignature=0x53425355;
                    	
        				/* If direction is device to host*/
        				if (gblCBW.bCBWFlags==0x80)
        				{
        					MSD_State=MSD_DATA_IN;
        				}
        				else if (gblCBW.bCBWFlags==0x00) 
            			{
        					/* If direction is host to device*/
        					/* prepare to read data in msd_buffer */
            			    MSD_State=MSD_DATA_OUT;
        				}        								
        			}
        		}
            }
            break;
        }
        case MSD_DATA_IN:
            if(MSDProcessCommand() == MSD_COMMAND_WAIT)
            {
                // Done processing the command, send the status
                MSD_State = MSD_SEND_CSW;
            }
            break;
        case MSD_DATA_OUT:
            if(MSDProcessCommand() == MSD_COMMAND_WAIT)
            {
    			/* Finished receiving the data prepare and send the status */
    		  	if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue!=0)) 
    		  	{
    		  		msd_csw.bCSWStatus=0x02;
    		    }
                MSD_State = MSD_SEND_CSW;
            }
            break;
        case MSD_SEND_CSW:
            if(USBHandleBusy(USBMSDInHandle))
            {
                //The TX buffer is not ready to send the status yet.
                break;
            }
            
            USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,(BYTE*)&msd_csw,MSD_CSW_SIZE);
            
            //Get ready for next command to come in
            if(!USBHandleBusy(USBMSDOutHandle))
            {
                USBMSDOutHandle = USBRxOnePacket(MSD_DATA_OUT_EP,(BYTE*)&msd_cbw,sizeof(msd_cbw));
            }
        
           	MSD_State=MSD_WAIT;
            break;
    }
    
    return MSD_State;
}
Exemple #14
0
BOOL hidHandleBusy(void)
{
    return USBHandleBusy(hidRxHandle);
}
Exemple #15
0
void ProcessCCID()
{
	static WORD CardPresentVerifyCounter = 0;
	static BOOL CardON = FALSE;
	BYTE i;
	BYTE ppsData[3]; 

	////// Detect Card Insertion and removal and transmit 	/////////////
	////// the status on interrupt endpoint 				/////////////

    if( !CardON && SC_CardPresent() )
    {
	    if( CardPresentVerifyCounter > 100 )
	    {
			if(!USBHandleBusy(usbCcidInterruptInHandle))
			{
		    	usbCcidBulkInEndpoint[0] = 0x50; //Msg Type
				usbCcidBulkInEndpoint[1] = 3;	//card present, change

		    	usbCcidInterruptInHandle = USBTxOnePacket(USB_EP_INT_IN, (BYTE*)&usbCcidBulkInEndpoint, 2);
		    	CardON = TRUE;
			}
		}
		else
			CardPresentVerifyCounter++;
	}
	else if( CardON && !SC_CardPresent() )
    {
	    SC_Shutdown();	//reset SC_Lib states and turn off hardware
		if(!USBHandleBusy(usbCcidInterruptInHandle))
		{
	    	usbCcidBulkInEndpoint[0] = 0x50; //Msg Type
			usbCcidBulkInEndpoint[1] = 2;	//card not present, change
	    	usbCcidInterruptInHandle = USBTxOnePacket(USB_EP_INT_IN, (BYTE*)&usbCcidBulkInEndpoint, 2);
	    	CardON = FALSE;
		}
	}
	else
		CardPresentVerifyCounter = 0;

	///// Process commands received on Bulk Endoint 		//////////////

    if(!USBHandleBusy(usbCcidBulkOutHandle))		//Check if the endpoint has received any data from the host.
    {
		union SLOT_STATUS card_st;
		BYTE ErrCode;
		static WORD TransactionCount=0;

		card_st.Val = 0;
		ErrCode     = 0; //clear error code
		
		
	    if(usbCcidOutPacketTrack == USB_CCID_BULK_OUT_FIRST_PACKET)
		{
            memset( pUsbCcidApdu->CCID_BulkOutBuffer, 0, sizeof(pUsbCcidApdu->CCID_BulkOutBuffer)) ;
            // copy the length from the CCID packet to a 32 Bit Variable.
	        usbCcidOutPacketLength.byte.LB = usbCcidBulkOutEndpoint[1];
	        usbCcidOutPacketLength.byte.HB = usbCcidBulkOutEndpoint[2];
	        usbCcidOutPacketLength.byte.UB = usbCcidBulkOutEndpoint[3];
	        usbCcidOutPacketLength.byte.MB = usbCcidBulkOutEndpoint[4];
	        usbCcidNoOfBytesToReceive = usbCcidOutPacketLength.Val + 10; // CCID command overhead is 10 bytes.
			
    	    for (i =0;i < USB_EP_SIZE;i++) // Copy received data from host to a temperary buffer
    	        pUsbCcidApdu->CCID_BulkOutBuffer[i] = usbCcidBulkOutEndpoint[i];

    	    if (usbCcidNoOfBytesToReceive > USB_EP_SIZE) // We still have more USB transactions to receive from host
    	    {
    	        usbCcidNoOfBytesToReceive = usbCcidNoOfBytesToReceive - USB_EP_SIZE;
    	        usbCcidOutPacketTrack = USB_CCID_BULK_OUT_SUBSEQUENT_PACKET;
    	        usbCcidBulkOutHandle = USBRxOnePacket(USB_EP_BULK_OUT,(BYTE*)&usbCcidBulkOutEndpoint,USB_EP_SIZE);
    	        return;
    	    }
    	    else // We have received everything from the host.
    	    {
        	    usbCcidNoOfBytesToReceive = 0;
        	    usbCcidOutPacketTrack = USB_CCID_BULK_OUT_FIRST_PACKET;
        	    TransactionCount =0;
        	}

        }
        else if (usbCcidOutPacketTrack == USB_CCID_BULK_OUT_SUBSEQUENT_PACKET)
        {
            // copy data to the APDU[];
            TransactionCount++;	
			if (usbCcidNoOfBytesToReceive > USB_EP_SIZE)
			{
            	for (i =0 ; i< USB_EP_SIZE; i++ )
                	pUsbCcidApdu->CCID_BulkOutBuffer[USB_EP_SIZE *  TransactionCount + i] = usbCcidBulkOutEndpoint[i];
			}
			else
			{
				for (i =0 ; i< usbCcidNoOfBytesToReceive; i++ )
                	pUsbCcidApdu->CCID_BulkOutBuffer[USB_EP_SIZE*TransactionCount+i] = usbCcidBulkOutEndpoint[i];

			}
    	    if (usbCcidNoOfBytesToReceive > USB_EP_SIZE) // We still have more bytes to receive from host
    	    {
    	        usbCcidNoOfBytesToReceive = usbCcidNoOfBytesToReceive - USB_EP_SIZE;
    	        usbCcidOutPacketTrack = USB_CCID_BULK_OUT_SUBSEQUENT_PACKET;
    	        usbCcidBulkOutHandle = USBRxOnePacket(USB_EP_BULK_OUT,(BYTE*)&usbCcidBulkOutEndpoint,USB_EP_SIZE);
                return;
    	    }
    	    else // We have received everything from the host.
    	    {
        	    usbCcidNoOfBytesToReceive = 0;
        	    TransactionCount =0;
        	    usbCcidOutPacketTrack = USB_CCID_BULK_OUT_FIRST_PACKET;
        	}

        }
		
        switch(pUsbCcidApdu->CCID_BulkOutBuffer[0])		//Data arrived, check what kind of command might be in the packet of data.
		{
			////////////////////////////////////////////////////////////////////////////////////
			case USB_CCID_PC_TO_RDR_ICC_POWER_ON:
			{
				if( !SC_CardPresent() ) //if Card is not present
				{
					//Card not present. send error reply
					card_st.Val 		= 0;
					card_st.ICC_Status	= GetCardStatus();
					card_st.CmdStatus	= 1; //Command Failed Code

					pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_DATA_BLOCK; 		//Msg Type
					pUsbCcidApdu->CCID_BulkInBuffer[7] = card_st.Val;  			//bStatus
					pUsbCcidApdu->CCID_BulkInBuffer[8] = USB_CCID_ICC_MUTE;					//bError ICC_MUTE
					pUsbCcidApdu->CCID_BulkInBuffer[9] = 0;
                    
                    USBCCIDSendDataToHost(pUsbCcidApdu->CCID_BulkInBuffer, 10 );
				}
				else  //else if Card is Present
				{
					SC_Initialize();
					if( SC_PowerOnATR() ) //Get ATR
					{
//						SC_DoPPS();	//switch baud rate based on ATR setting	
                        if (SC_T0ProtocolType() && !SC_T1ProtocolType())
                            usbCcidProtocolNum = USB_CCID_T0_PROTOCOL; 	
                        else if (!SC_T0ProtocolType() && SC_T1ProtocolType())
                            usbCcidProtocolNum = USB_CCID_T1_PROTOCOL; 
                        			
						card_st.Val 		= 0;
						card_st.ICC_Status	= GetCardStatus();
						card_st.CmdStatus	= 0; //processed without error

					    // ATR success
						pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_DATA_BLOCK; 		//Msg Type

						pUsbCcidApdu->CCID_BulkInBuffer[1] = scATRLength;
						pUsbCcidApdu->CCID_BulkInBuffer[2] = 0;
						pUsbCcidApdu->CCID_BulkInBuffer[3] = usbCcidBulkInEndpoint[4] = 0;

						pUsbCcidApdu->CCID_BulkInBuffer[7] = card_st.Val;  //bStatus
						pUsbCcidApdu->CCID_BulkInBuffer[8] = 0;			//bError
						pUsbCcidApdu->CCID_BulkInBuffer[9] = 0;  //no extended APDU support

						for (i = 0; i < scATRLength; i++)
						    pUsbCcidApdu->CCID_BulkInBuffer[10 + i] = scCardATR[i];
						USBCCIDSendDataToHost(pUsbCcidApdu->CCID_BulkInBuffer, scATRLength+10 );
				    }
			        else // ATR Failed
			        {
					    // Reply with Error response
					    card_st.ICC_Status	= 1;  // from CCID Rev 1.1 page 28.  Error codes for Hardware Error
					    card_st.CmdStatus	= 1;  // Command Failed
					    ErrCode     		= USB_CCID_HW_ERROR;  // Hardware Error

					    pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_DATA_BLOCK; 		//Msg Type
					    pUsbCcidApdu->CCID_BulkInBuffer[7] = card_st.Val;  //bStatus
					    pUsbCcidApdu->CCID_BulkInBuffer[8] = ErrCode;		//bError
					    pUsbCcidApdu->CCID_BulkInBuffer[9] = 0;
                        USBCCIDSendDataToHost(pUsbCcidApdu->CCID_BulkInBuffer, 10 );
				    }// End of else ATR Failed
			    }// End of else - card is present
			}// End case PC_to_RDR_IccPowerOn:    
			break;

			////////////////////////////////////////////////////////////////////////////////////
			case USB_CCID_PC_TO_RDR_ICC_POWER_OFF:
			    if( pUsbCcidApdu->CCID_BulkOutBuffer[5] == 0 )	// must be slot 0 (for 1 slot reader)
			    {
				    //Do power off sequence if required
				    SC_Shutdown();
				    card_st.ICC_Status	= GetCardStatus();	// bStatus - 0 Card Present and active,
														        //           1 Card Present and inactive,
														        //			 2 Not Present
			    }
			    else //slot # out of range
			    {
				    card_st.ICC_Status	= 2;  // from CCID Rev 1.1 page 28.  Error codes for bad slot umber
				    card_st.CmdStatus	= 1;  // Command Failed
				    ErrCode     		= 5;  // bError Slot Does not exist
			    }

			    pUsbCcidApdu->CCID_BulkInBuffer[0] = 0x81; //Msg Type
			    pUsbCcidApdu->CCID_BulkInBuffer[7] = card_st.Val;  //bStatus
			    pUsbCcidApdu->CCID_BulkInBuffer[8] = ErrCode;		//bError
			    pUsbCcidApdu->CCID_BulkInBuffer[9] = (SC_GetCardState()==SC_STATE_CARD_ACTIVE)?0:1;  //Clock Status: 0 Running, 1 Stopped L, 2 Stopped H
                USBCCIDSendDataToHost(pUsbCcidApdu->CCID_BulkInBuffer, 10 );
            break;

            ////////////////////////////////////////////////////////////////////////////////////
            case USB_CCID_PC_TO_RDR_GET_SLOT_STATUS:
                if( pUsbCcidApdu->CCID_BulkOutBuffer[5] == 0 )	// must be slot 0 (for 1 slot reader)
			    {
				    card_st.ICC_Status	= GetCardStatus();	// bStatus - 0 Card Present and active,
														    //           1 Card Present and inactive,
														    //			 2 Not Present
			    }
			    else //slot # out of range
			    {
				    card_st.ICC_Status	= 2;  // from CCID Rev 1.1 page 28.  Error codes for bad slot umber
				    card_st.CmdStatus	= 1;  // Command Failed
				    ErrCode     		= 5;  // bError Slot Does not exist
			    }

			    pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_SLOT_STATUS; //Msg Type
			    pUsbCcidApdu->CCID_BulkInBuffer[7] = card_st.Val;  //bStatus
			    pUsbCcidApdu->CCID_BulkInBuffer[8] = ErrCode;		//bError
			    pUsbCcidApdu->CCID_BulkInBuffer[9] = (SC_GetCardState()==SC_STATE_CARD_ACTIVE)?0:1;  //Clock Status: 0 Running, 1 Stopped L, 2 Stopped H
			    USBCCIDSendDataToHost(pUsbCcidApdu->CCID_BulkInBuffer, 10 );
            break;

            ////////////////////////////////////////////////////////////////////////////////////
			case USB_CCID_PC_TO_RDR_XFR_BLOCK:
			    UsbCcidPcToRdrXfrBlock();
			break;

            ////////////////////////////////////////////////////////////////////////////////////
            
			case USB_CCID_PC_TO_RDR_GET_PARAMETERS:
			    UsbCcidSendRdrToPcParameters(); 
			break;
			////////////////////////////////////////////////////////////////////////////////////
			case USB_CCID_PC_TO_RDR_RESET_PARAMETERS :
			    UsbCcidSendRdrToPcParameters();
			break;
			////////////////////////////////////////////////////////////////////////////////////
			case USB_CCID_PC_TO_RDR_SET_PARAMETERS :
			    if  (SC_GetCardState() == SC_STATE_CARD_ACTIVE)
				{
    				if (SC_T0ProtocolType() && SC_T1ProtocolType())
    				{
    				    usbCcidProtocolNum = pUsbCcidApdu->CCID_BulkOutBuffer[7];  
    				}    
    				ppsData[0] = 0xFF; 
					if (usbCcidProtocolNum == USB_CCID_T0_PROTOCOL)   //if T=0 Protocol
					{
    					//pUsbCcidApdu->CCID_BulkOutBuffer[10]; //Read FI Index
    					//pUsbCcidApdu->CCID_BulkOutBuffer[11]; //bmTCCKST0    
    					//pUsbCcidApdu->CCID_BulkOutBuffer[12]; // Read Guard Time
    					//pUsbCcidApdu->CCID_BulkOutBuffer[13]; // Read WI
    					ppsData[1] = 0x00; 
    					
    	            }
    	            else if (usbCcidProtocolNum == USB_CCID_T1_PROTOCOL) 
    	            {
        	            ppsData[1] = 0x01;
        	            //pUsbCcidApdu->CCID_BulkOutBuffer[10]; //Read FI Index
    					//pUsbCcidApdu->CCID_BulkOutBuffer[11]; //bmTCCKST1    
    					//pUsbCcidApdu->CCID_BulkOutBuffer[12]; // Guard Time
    					//pUsbCcidApdu->CCID_BulkOutBuffer[13]; // bmWaitingIntegersT1
    					//pUsbCcidApdu->CCID_BulkOutBuffer[14]; // bClockStop
    					//pUsbCcidApdu->CCID_BulkOutBuffer[15]; //bIFSC
    					//pUsbCcidApdu->CCID_BulkOutBuffer[16]; //bNadValue
        	        } 
        	        ppsData[2] = ppsData[0] ^ ppsData[1];  
        	        if (SC_T0ProtocolType() && SC_T1ProtocolType()) 
        	        {  		    
    			        if (!SC_DoPPS(ppsData))
    			        {
        		            SC_Shutdown();
        			    }
        			}   
    				ccid_clockstatus = pUsbCcidApdu->CCID_BulkOutBuffer[14]; // Read Clock Stop Status
                }
                UsbCcidSendRdrToPcParameters();				
			break;
		
			#ifndef LOW_PIN_COUNT_USB_DEVELOPMENT_KIT
            ////////////////////////////////////////////////////////////////////////////////////
            case USB_CCID_PC_TO_RDR_ESCAPE:
                // This Command is not supoprted
                pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_ESCAPE;
				UsbCcidCommandNotSupported();
                
            break;
			#endif
			
            ////////////////////////////////////////////////////////////////////////////////////
            case USB_CCID_PC_TO_RDR_ICC_CLOCK:
                if( pUsbCcidApdu->CCID_BulkOutBuffer[5] == 0 )	// must be slot 0 (for 1 slot reader)
			    {
					//Do power off sequence if required
				    if (pUsbCcidApdu->CCID_BulkOutBuffer[7] == 0)
					{
				        USB_CCID_RestartClock();//Restart Clock
					}
				    else if (pUsbCcidApdu->CCID_BulkOutBuffer[7] == 1)
				    {
				        if (ccid_clockstatus == 1)
						{
				        	USB_CCID_StopClockWithPinLow(); // Stop with Clock signal Low
						}
				        else if (ccid_clockstatus == 2)
						{
				            USB_CCID_StopClockWithPinHigh();// Stop with Clock signal High
						}
				        else if (ccid_clockstatus == 3)
						{
    				        USB_CCID_StopClockWithPinLow(); // Stop with Clock either High or Low
						}
				     }
				     card_st.ICC_Status	= GetCardStatus();	// bStatus - 0 Card Present and active,
														        //           1 Card Present and inactive,
														        //			 2 Not Present
			    }
			    else //slot # out of range
			    {
				    card_st.ICC_Status	= 2;  // from CCID Rev 1.1 page 28.  Error codes for bad slot umber
				    card_st.CmdStatus	= 1;  // Command Failed
				    ErrCode     		= 5;  // bError Slot Does not exist
			    }
			    pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_SLOT_STATUS; //Msg Type
			    pUsbCcidApdu->CCID_BulkInBuffer[7] = card_st.Val;  //bStatus
			    pUsbCcidApdu->CCID_BulkInBuffer[8] = ErrCode;		//bError
			    pUsbCcidApdu->CCID_BulkInBuffer[9] = (SC_GetCardState()==SC_STATE_CARD_ACTIVE)?0:1;  //Clock Status: 0 Running, 1 Stopped L, 2 Stopped H
					
				USBCCIDSendDataToHost(pUsbCcidApdu->CCID_BulkInBuffer, 10 );
            break;

            ////////////////////////////////////////////////////////////////////////////////////
			#ifndef LOW_PIN_COUNT_USB_DEVELOPMENT_KIT
            case USB_CCID_PC_TO_RDR_SECURE :
                // This Command is not supoprted
                pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_DATA_BLOCK;
                UsbCcidCommandNotSupported();
            break;

            ////////////////////////////////////////////////////////////////////////////////////
            case USB_CCID_PC_TO_RDR_MECHANICAL:
                // This Command is not supoprted
				pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_SLOT_STATUS;
				UsbCcidCommandNotSupported();
            ////////////////////////////////////////////////////////////////////////////////////
            case USB_CCID_PC_TO_RDR_ABORT:
                // This Command is not supoprted
				pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_SLOT_STATUS;
				UsbCcidCommandNotSupported();

            ////////////////////////////////////////////////////////////////////////////////////
            case USB_CCID_PC_TO_RDR_SET_DATA_RATE_AND_CLOCK_FREQUENCY:
                // This Command is not supoprted
				pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_DATA_RATE_AND_CLOCK_FREQUENCY;
				UsbCcidCommandNotSupported();

            ////////////////////////////////////////////////////////////////////////////////////
            case USB_CCID_PC_TO_RDR_T0APDU :
                // This Command is not supoprted
                pUsbCcidApdu->CCID_BulkInBuffer[0] = USB_CCID_RDR_TO_PC_SLOT_STATUS;
                UsbCcidCommandNotSupported();
            break;
 			#endif
            default:
                pUsbCcidApdu->CCID_BulkInBuffer[0] =  USB_CCID_RDR_TO_PC_SLOT_STATUS;
				#ifndef LOW_PIN_COUNT_USB_DEVELOPMENT_KIT
					UsbCcidCommandNotSupported();  
				#else
					card_st.Val 		= 0;
					card_st.ICC_Status	= GetCardStatus();
					card_st.CmdStatus	= 1; //Command Failed Code
					pUsbCcidApdu->CCID_BulkInBuffer[7] = card_st.Val;  //bStatus
    				pUsbCcidApdu->CCID_BulkInBuffer[8] = USB_CCID_CMD_NOT_SUPPORTED; //bError, Command not supported
					USBCCIDSendDataToHost(pUsbCcidApdu->CCID_BulkInBuffer, 10 );  
				#endif 
            break;
        }
        usbCcidBulkOutHandle = USBRxOnePacket(USB_EP_BULK_OUT,(BYTE*)&usbCcidBulkOutEndpoint,USB_EP_SIZE);
    }
}
/*********************************************************************
* Function: void APP_DeviceVendorThroughputTestTasks(void);
*
* Overview: keeps the demo running.
*
* PreCondition: Demo is initialiized.
*
* Input: None
*
* Output: None
*
********************************************************************/
void APP_DeviceVendorThroughputTestTasks()
{
    //User Application USB tasks below.
    //Note: The user application should not begin attempting to read/write over the USB
    //until after the device has been fully enumerated.  After the device is fully
    //enumerated, the USBDeviceState will be set to "CONFIGURED_STATE".
    if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;

    //All currently existing Microchip USB microcontroller use a dedicated Direct
    //Memory Access (DMA) interface allowing the USB module to directly read or
    //write USB packets into or out of microcontroller SRAM.  To receive an "OUT"
    //packet from the host (in USB terminology, OUT and IN are always from the host's
    //perspective), the microcontroller firmware needs to "arm" the Buffer
    //Descriptor Table (BDT) for the endpoint that the data will be received on.
    //The BDT entry is a small set of special function registers (SFRs) that
    //control the operation of the DMA transaction (number of bytes to receive,
    //pointer to where in SRAM the data should be placed, etc.).  Depending upon
    //the USB module configuration, there will be many BDT entries, as each
    //combination of endpoint number, endpoint direction, and endpoint
    //"even/odd-ness" (when ping-pong buffering is enabled), needs a dedicated
    //set of SFRs for controling the DMA behavior when the host tries to read/write
    //to the respective endpoint.

    //As the device completes the enumeration process, the USBCBInitEP() function will
    //get called.  In this function, we initialize the user application endpoints (in this
    //example code, the user application makes use of EP1 OUT, EP2 OUT, EP3 OUT).
    //The USBTransferOnePacket() function calls in the USBCBInitEP() function initializes an endpoint
    //and "arms" it so that it can receive a packet of data from the host.  Once the endpoint
    //has been armed, the host can then send data to it (assuming some kind of application software
    //is running on the host, and the application software tries to send data to the USB device).

    //If the host sends a packet of data to the endpoint 1 OUT buffer, the hardware of the SIE will
    //automatically receives it and stores the data at the memory location pointed to when we called
    //USBTransferOnePacket().  Additionally, the endpoint handle will indicate
    //that the endpoint is no longer busy.  At this point, it is safe for this firmware to begin reading
    //from the endpoint buffer, and processing the data.  In this example, we don't actually do anything
    //with the data that is received from the host, since this demo is simply meant to show high bandwidth
    //USB communication.

    //This demo makes full use of the "ping-pong" buffering features implemented
    //by the USB module hardware.  Ping-pong buffering is like a "DMA FIFO".
    //It enables up to two transactions to be queued up on a single endpoint.
    //While the firmware may be processing and using previously received data,
    //the USB module hardware can be configured to still receive the next packet
    //of data that may be sent from the host.


    //As an example in the below code, if the USB host tries to send 273 bytes
    //to "Endpoint 1 OUT", the following sequence will occur:

    //1. The first set of bytes (0-63) will arrive in the EP1OUTEvenBuffer[].
    //2. The next set of bytes (64-127) will arrive in the EP1OUTOddBuffer[].
    //3. Assuming the firmware re-armed the EP1OUTEven BDT, then the next set of
   	//		bytes (128-191) will arrive in the EP1OUTEvenBuffer[].
    //4. Assuming the firmware re-armed the EP1OUTOdd BDT, then the next set of
   	//		bytes (192-255) will arrive in the EP1OUTOddBuffer[].
    //5. Assuming the firmware re-armed the EP1OUTEven BDT, then the next set of
   	//		bytes (256-272) will arrive in the EP1OUTEvenBuffer[]. This completes
   	//		the transfer, as the host has successfully sent 273 bytes total (0-272).

   	//If after successfully completing the above 273 byte transfer, and the host
   	//wants to start another transfer and send another 75 bytes, the following
   	//will occur:

    //6. Assuming the firmware re-armed the EP1OUTOdd BDT, then bytes (0-63)
    //		will arrive in the EP1OUTOddBuffer[].
    //7. Assuming the firmware re-armed the EP1OUTEven BDT, then the next set of
   	//		bytes (64-74) will arrive in the EP1OUTEvenBuffer[]. This completes
   	//		the transfer, as the host has successfully sent 75 bytes total (0-74).

   	//In the above sequence, if the firmware had not gotten around to re-arming
   	//the EP1OUTEven BDT by step #3, then the EP1 OUT endpoint will continuously
   	//NAK until the firmware eventually does re-arm the EP1OUTEven BDT.  This
   	//NAKing will temporarily halt the data flow, but it does not cause data to
   	//be lost.  The host will continue to retry sending the data until it is
   	//received successfully, or, the host PC application that is sending the data
   	//aborts the operation.  The PC application software can be written to
   	//optionally abort a transfer if it takes too long (or some other event
   	//takes place, such as the user trying to close the application).


    if(EP1OUTEvenNeedsServicingNext == true)	//Check which buffer (even/odd) the next set of data is going to arrive in
    {
        if(!USBHandleBusy(EP1OUTEvenHandle))	//Check if the endpoint has received any data from the host.
        {
            //If the microcontroller core gets to this point, it means that the host has
            //successfully sent data to the EP1 OUT endpoint, and the data in the EP1OUTEvenBuffer[]
            //is currently valid.

            //Insert code here that would do something useful with the EP1OUTEvenBuffer[]
            //data, according to the needs of the application.  For this high-bandwidth
            //example application, we don't do anything with the data, as the
            //objective is to demonstrate maximum data transfer rate only.

            //Now re-arm the EP1OUTEven BDT entry so that the EP1OUTEvenBuffer[] can
            //be prepared to receive the "second to next" data packet that the host
            //sends to EP1 OUT.  The very next data packet sent to EP1 OUT will go
            //into the EP1OUTOdd buffer.  However, we still need to re-arm the
            //EP1OUTEven BDT entry, so that the data packet that arrives after the
            //one going into the EP1OUTOdd buffer has someplace to go.

            //The USBTransferOnePacket() function call "arms" the endpoint (and
            //makes it "busy").  If the endpoint is armed, the SIE will automatically
            //accept data from the host, if the host tries to send a packet of data
            //to the endpoint.  Once a data packet addressed to this endpoint is
            //received from the host, the endpoint will no longer be busy, and the
            //application can read the data which will be sitting in the buffer.
            EP1OUTEvenHandle = USBTransferOnePacket(1, OUT_FROM_HOST,(uint8_t*)&EP1OUTEvenBuffer,64);
            EP1OUTEvenNeedsServicingNext = false;
        }
    }
    else //else EP1OUTOdd needs servicing next
    {
        if(!USBHandleBusy(EP1OUTOddHandle))		//Check if the endpoint has received any data from the host.
        {
                //Insert code here that would do something useful with the data, according to the needs of
                //the application.

            //Re-arm the EP1OUTOdd BDT entry so the EP1OUTOddBuffer[] can receive
            //the second to next data packet sent by the host.
            EP1OUTOddHandle = USBTransferOnePacket(1, OUT_FROM_HOST,(uint8_t*)&EP1OUTOddBuffer,64);
            EP1OUTEvenNeedsServicingNext = true;
        }
    }

    if(EP2OUTEvenNeedsServicingNext == true)
    {
        if(!USBHandleBusy(EP2OUTEvenHandle))		//Check if the endpoint has received any data from the host.
        {
            //Re-arm the OUT endpoint for the next packet:
            EP2OUTEvenHandle = USBTransferOnePacket(2, OUT_FROM_HOST,(uint8_t*)&EP2OUTEvenBuffer,64);
            EP2OUTEvenNeedsServicingNext = false;
        }
    }
    else //else EP2OUTOdd needs servicing next
    {
        if(!USBHandleBusy(EP2OUTOddHandle))		//Check if the endpoint has received any data from the host.
        {
            //Re-arm the OUT endpoint for the next packet:
            EP2OUTOddHandle = USBTransferOnePacket(2, OUT_FROM_HOST,(uint8_t*)&EP2OUTOddBuffer,64);
            EP2OUTEvenNeedsServicingNext = true;
        }
    }

    if(EP3OUTEvenNeedsServicingNext == true)
    {
        if(!USBHandleBusy(EP3OUTEvenHandle))		//Check if the endpoint has received any data from the host.
        {
            //Re-arm the OUT endpoint for the next packet:
            EP3OUTEvenHandle = USBTransferOnePacket(3, OUT_FROM_HOST,(uint8_t*)&EP3OUTEvenBuffer,64);
            EP3OUTEvenNeedsServicingNext = false;
        }
    }
    else //else EP3OUTOdd needs servicing next
    {
        if(!USBHandleBusy(EP3OUTOddHandle))		//Check if the endpoint has received any data from the host.
        {
            //Re-arm the OUT endpoint for the next packet:
            EP3OUTOddHandle = USBTransferOnePacket(3, OUT_FROM_HOST,(uint8_t*)&EP3OUTOddBuffer,64);
            EP3OUTEvenNeedsServicingNext = true;
        }
    }
}
/******************************************************************************
 	Function:
 		BYTE MSDWriteHandler(void)
 		
 	Description:
 		This funtion processes a write command received through 
 		the MSD class driver
 		
 	PreCondition:
 		None
 		
 	Parameters:
 		None
 		
 	Return Values:
 		BYTE - the current state of the MSDWriteHandler state
 		machine.  The valid values are defined in MSD.h under the 
 		MSDWriteHandler state machine declaration section
 		
 	Remarks:
 		None
 
 *****************************************************************************/
BYTE MSDWriteHandler(void)
{
    switch(MSDWriteState)
    {
        case MSD_WRITE10_WAIT:
         	/* Read the LBA, TransferLength fields from Command Block
               NOTE: CB is Big-Endian */
        
        	LBA.v[3]=gblCBW.CBWCB[2];
        	LBA.v[2]=gblCBW.CBWCB[3];
        	LBA.v[1]=gblCBW.CBWCB[4];
        	LBA.v[0]=gblCBW.CBWCB[5];
        	TransferLength.v[1]=gblCBW.CBWCB[7];
        	TransferLength.v[0]=gblCBW.CBWCB[8];
        
        	//Initially assume success, unless handler code later encounters an
        	//error condition and sets the status to 0x01 or 0x02.
        	msd_csw.bCSWStatus=0x0;	
        	
        	MSD_State = MSD_WRITE10_BLOCK;
        	//Fall through to MSD_WRITE10_BLOCK
        case MSD_WRITE10_BLOCK:
            if(TransferLength.Val == 0)
            {
                MSDWriteState = MSD_WRITE10_WAIT;
                break;
            }
            
            MSDWriteState = MSD_WRITE10_RX_SECTOR;
            ptrNextData=(BYTE *)&msd_buffer[0];
              
        	msd_csw.dCSWDataResidue=BLOCKLEN_512;
        	
            //Fall through to MSD_WRITE10_RX_SECTOR
        case MSD_WRITE10_RX_SECTOR:
        {
      		/* Read 512B into msd_buffer*/
      		if(msd_csw.dCSWDataResidue>0) 
      		{
                if(USBHandleBusy(USBMSDOutHandle) == TRUE)
                {
                    break;
                }

                USBMSDOutHandle = USBRxOnePacket(MSD_DATA_OUT_EP,ptrNextData,MSD_OUT_EP_SIZE);
                MSDWriteState = MSD_WRITE10_RX_PACKET;
                //Fall through to MSD_WRITE10_RX_PACKET
      	    }
      	    else
      	    {
          		//We finished receiving a sector worth of data from the host.
          		//Check if the media is write protected before deciding what
          		//to do with the data.
          		if(LUNWriteProtectState()) 
                {
                    //The device appears to be write protected.
              	    //Let host know error occurred.  The bCSWStatus flag is also used by
              	    //the write handler, to know not to even attempt the write sequence.
              	    msd_csw.bCSWStatus=0x01;    
              	    
                    //Set sense keys so the host knows what caused the error.
              	    gblSenseData[LUN_INDEX].SenseKey=S_NOT_READY;
              	    gblSenseData[LUN_INDEX].ASC=ASC_WRITE_PROTECTED;
              	    gblSenseData[LUN_INDEX].ASCQ=ASCQ_WRITE_PROTECTED;
              	}
   			    MSDWriteState = MSD_WRITE10_SECTOR;     
      			break;
          	}
        }
        //Fall through to MSD_WRITE10_RX_PACKET
        case MSD_WRITE10_RX_PACKET:
            if(USBHandleBusy(USBMSDOutHandle) == TRUE)
            {
                break;
            }
            
        	gblCBW.dCBWDataTransferLength-=USBHandleGetLength(USBMSDOutHandle);		// 64B read
        	msd_csw.dCSWDataResidue-=USBHandleGetLength(USBMSDOutHandle);
            ptrNextData += MSD_OUT_EP_SIZE;
            
            MSDWriteState = MSD_WRITE10_RX_SECTOR;
            break;
        case MSD_WRITE10_SECTOR:
        {
            //Make sure that no error has been detected, before performing the write
            //operation.  If there was an error, skip the write operation, but allow
            //the TransferLength to continue decrementing, so that we can eventually
            //receive all OUT bytes that the host is planning on sending us.  Only
            //after that is complete will the host send the IN token for the CSW packet,
            //which will contain the bCSWStatus letting it know an error occurred.
      		if(msd_csw.bCSWStatus == 0x00)
      		{
          		if(LUNSectorWrite(LBA.Val, (BYTE*)&msd_buffer[0], (LBA.Val==0)?TRUE:FALSE) != TRUE)
          		{
              		//The write operation failed for some reason.  Keep track of retry
              		//attempts and abort if repeated write attempts also fail.
    				if(MSDRetryAttempt < MSD_FAILED_WRITE_MAX_ATTEMPTS)
    				{
    				    MSDRetryAttempt++;
                        break;
    				}
    				else
    				{  
        				//Too many consecutive failed write attempts have occurred. 
        				//Need to give up and abandon the write attempt.
        				msd_csw.bCSWStatus=0x01;		// Error 0x01 Refer page#18
                                                        // of BOT specifications
                        //Set error status sense keys, so the host can check them later
                        //to determine how to proceed.
                        gblSenseData[LUN_INDEX].SenseKey=S_MEDIUM_ERROR;
    			        gblSenseData[LUN_INDEX].ASC=ASC_NO_ADDITIONAL_SENSE_INFORMATION;
    			        gblSenseData[LUN_INDEX].ASCQ=ASCQ_NO_ADDITIONAL_SENSE_INFORMATION;
                    }              		
          		}
      		}
      
            //One LBA is written (unless an error occurred).  Advance state
            //variables so we can eventually finish handling the CBW request.
      		LBA.Val++;				
      		TransferLength.Val--;      
            MSDWriteState = MSD_WRITE10_BLOCK;
            break;
        } 
        
        default:
            //Illegal condition which should not occur.  If for some reason it
            //does, try to let the host know know an error has occurred.
            msd_csw.bCSWStatus=0x02;    //Phase Error
            MSDWriteState = MSD_WRITE10_WAIT;            
    }
    
    return MSDWriteState;
}
/*********************************************************************
* Function: void APP_DeviceAudioMIDITasks(void);
*
* Overview: Keeps the Custom HID demo running.
*
* PreCondition: The demo should have been initialized and started via
*   the APP_DeviceAudioMIDIInitialize() and APP_DeviceAudioMIDIStart() demos
*   respectively.
*
* Input: None
*
* Output: None
*
********************************************************************/
void APP_DeviceAudioMIDITasks()
{
    /* If the device is not configured yet, or the device is suspended, then
     * we don't need to run the demo since we can't send any data.
     */
    if( (USBGetDeviceState() < CONFIGURED_STATE) ||
        (USBIsDeviceSuspended() == true))
    {
        return;
    }

    if(!USBHandleBusy(USBRxHandle))
    {
        //We have received a MIDI packet from the host, process it and then
        //  prepare to receive the next packet

        //INSERT MIDI PROCESSING CODE HERE

        //Get ready for next packet (this will overwrite the old data)
        USBRxHandle = USBRxOnePacket(USB_DEVICE_AUDIO_MIDI_ENDPOINT,(uint8_t*)&ReceivedDataBuffer,64);
    }

    /* If the user button is pressed... */
    if(BUTTON_IsPressed(BUTTON_DEVICE_AUDIO_MIDI) == true)
    {
        /* and we haven't sent a transmission in the past 100ms... */
        if(msCounter == 0)
        {
            /* and we have sent the NOTE_OFF for the last note... */
            if(sentNoteOff == true)
            {
                /* and we aren't currently trying to transmit data... */
                if(!USBHandleBusy(USBTxHandle))
                {
                    //Then reset the 100ms counter
                    msCounter = 100;

                    midiData.Val = 0;   //must set all unused values to 0 so go ahead
                                        //  and set them all to 0

                    midiData.CableNumber = 0;
                    midiData.CodeIndexNumber = MIDI_CIN_NOTE_ON;
                    midiData.DATA_0 = 0x90;         //Note on
                    midiData.DATA_1 = pitch;         //pitch
                    midiData.DATA_2 = 0x7F;  //velocity

                    USBTxHandle = USBTxOnePacket(USB_DEVICE_AUDIO_MIDI_ENDPOINT,(uint8_t*)&midiData,4);

                    /* we now need to send the NOTE_OFF for this note. */
                    sentNoteOff = false;
                }
            }
        }
    }
    else
    {
        if(msCounter == 0)
        {
            if(sentNoteOff == false)
            {
                if(!USBHandleBusy(USBTxHandle))
                {
                    //Debounce counter for 100ms
                    msCounter = 100;

                    midiData.Val = 0;   //must set all unused values to 0 so go ahead
                                        //  and set them all to 0

                    midiData.CableNumber = 0;
                    midiData.CodeIndexNumber = MIDI_CIN_NOTE_ON;
                    midiData.DATA_0 = 0x90;     //Note off
                    midiData.DATA_1 = pitch++;     //pitch
                    midiData.DATA_2 = 0x00;        //velocity

                    if(pitch == 0x49)
                    {
                        pitch = 0x3C;
                    }

                    USBTxHandle = USBTxOnePacket(USB_DEVICE_AUDIO_MIDI_ENDPOINT,(uint8_t*)&midiData,4);
                    sentNoteOff = true;
                }
            }
        }
    }
}
BYTE MSDReadHandler(void)
{
    switch(MSDReadState)
    {
        case MSD_READ10_WAIT:
        	LBA.v[3]=gblCBW.CBWCB[2];
        	LBA.v[2]=gblCBW.CBWCB[3];
        	LBA.v[1]=gblCBW.CBWCB[4];
        	LBA.v[0]=gblCBW.CBWCB[5];
        	
        	TransferLength.v[1]=gblCBW.CBWCB[7];
        	TransferLength.v[0]=gblCBW.CBWCB[8];

            //Assume success initially, msd_csw.bCSWStatus will get set to 0x01 
            //or 0x02 later if an error is detected during the actual read sequence.        	
        	msd_csw.bCSWStatus=0x0;
        	msd_csw.dCSWDataResidue=0x0;
        	
            MSDReadState = MSD_READ10_BLOCK;
            //Fall through to MSD_READ_BLOCK
        case MSD_READ10_BLOCK:
            if(TransferLength.Val == 0)
            {
                MSDReadState = MSD_READ10_WAIT;
                break;
            }
            
            TransferLength.Val--;					// we have read 1 LBA
            MSDReadState = MSD_READ10_SECTOR;
            //Fall through to MSD_READ10_SECTOR
        case MSD_READ10_SECTOR:
            //if the old data isn't completely sent yet
            if(USBHandleBusy(USBMSDInHandle) != 0)
            {
                break;
            }
            
            //Try to read a sector worth of data from the media, but check for
            //possible errors.
    		if(LUNSectorRead(LBA.Val, (BYTE*)&msd_buffer[0]) != TRUE)
    		{
				if(MSDRetryAttempt < MSD_FAILED_READ_MAX_ATTEMPTS)
				{
				    MSDRetryAttempt++;
                    break;
				}
				else
				{  
    				//Too many consecutive failed reads have occurred.  Need to
    				//give up and abandon the sector read attempt; something must
    				//be wrong and we don't want to get stuck in an infinite loop.
    				//Need to indicate to the host that a device error occurred.
    				//However, we can't send the CSW immediately, since the host
    				//still expects to receive sector read data on the IN endpoint 
    				//first.  Therefore, we still send dummy bytes, before
    				//we send the CSW with the failed status in it.
    				msd_csw.bCSWStatus=0x01;		// Error 0x01 Refer page#18
                                                    // of BOT specifications
                    //Set error status sense keys, so the host can check them later
                    //to determine how to proceed.
                    gblSenseData[LUN_INDEX].SenseKey=S_MEDIUM_ERROR;
			        gblSenseData[LUN_INDEX].ASC=ASC_NO_ADDITIONAL_SENSE_INFORMATION;
			        gblSenseData[LUN_INDEX].ASCQ=ASCQ_NO_ADDITIONAL_SENSE_INFORMATION;
                }
            }//else we successfully read a sector worth of data from our media

            LBA.Val++;
			msd_csw.dCSWDataResidue=BLOCKLEN_512;//in order to send the
                                                 //512 bytes of data read
                                                 
            ptrNextData=(BYTE *)&msd_buffer[0];
            
            MSDReadState = MSD_READ10_TX_SECTOR;
    
            //Fall through to MSD_READ10_TX_SECTOR
        case MSD_READ10_TX_SECTOR:
            if(msd_csw.dCSWDataResidue == 0)
            {
                MSDReadState = MSD_READ10_BLOCK;
                break;
            }
            
            MSDReadState = MSD_READ10_TX_PACKET;
            //Fall through to MSD_READ10_TX_PACKET
            
        case MSD_READ10_TX_PACKET:
    		/* Write next chunk of data to EP Buffer and send */
            
            //Make sure the endpoint is available before using it.
            if(USBHandleBusy(USBMSDInHandle))
            {
                break;
            }
            //Prepare the USB module to send an IN transaction worth of data to the host.
            USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,ptrNextData,MSD_IN_EP_SIZE);
            
 			MSDReadState = MSD_READ10_TX_SECTOR;

    		gblCBW.dCBWDataTransferLength-=	MSD_IN_EP_SIZE;
    		msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE;
    		ptrNextData+=MSD_IN_EP_SIZE;
            break;
        
        default:
            //Illegal condition, should never occur.  In the event that it ever
            //did occur anyway, try to notify the host of the error.
            msd_csw.bCSWStatus=0x02;  //indicate "Phase Error"
            //Advance state machine
            MSDReadState = MSD_READ10_WAIT;
    }
    
    return MSDReadState;
}
/******************************************************************************
 * Function:        void ProcessIO(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function is a place holder for other user routines.
 *                  It is a mixture of both USB and non-USB tasks.
 *
 * Note:            None
 *****************************************************************************/
void ProcessIO(void)
{   
    //Blink the LEDs according to the USB device status, but only do so if the PC application isn't connected and controlling the LEDs.
    if(blinkStatusValid)
    {
        BlinkUSBStatus();
    }

    //User Application USB tasks below.
    //Note: The user application should not begin attempting to read/write over the USB
    //until after the device has been fully enumerated.  After the device is fully
    //enumerated, the USBDeviceState will be set to "CONFIGURED_STATE".
    if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;
    
    //As the device completes the enumeration process, the USBCBInitEP() function will
    //get called.  In this function, we initialize the user application endpoints (in this
    //example code, the user application makes use of endpoint 1 IN and endpoint 1 OUT).
    //The USBGenRead() function call in the USBCBInitEP() function initializes endpoint 1 OUT
    //and "arms" it so that it can receive a packet of data from the host.  Once the endpoint
    //has been armed, the host can then send data to it (assuming some kind of application software
    //is running on the host, and the application software tries to send data to the USB device).
    
    //If the host sends a packet of data to the endpoint 1 OUT buffer, the hardware of the SIE will
    //automatically receive it and store the data at the memory location pointed to when we called
    //USBGenRead().  Additionally, the endpoint handle (in this case USBGenericOutHandle) will indicate
    //that the endpoint is no longer busy.  At this point, it is safe for this firmware to begin reading
    //from the endpoint buffer, and processing the data.  In this example, we have implemented a few very
    //simple commands.  For example, if the host sends a packet of data to the endpoint 1 OUT buffer, with the
    //first byte = 0x80, this is being used as a command to indicate that the firmware should "Toggle LED(s)".
    if(!USBHandleBusy(USBGenericOutHandle))		//Check if the endpoint has received any data from the host.
    {   
        switch(OUTPacket[0])					//Data arrived, check what kind of command might be in the packet of data.
        {
            case 0x80:  //Toggle LED(s) command from PC application.
		        blinkStatusValid = FALSE;		//Disable the regular LED blink pattern indicating USB state, PC application is controlling the LEDs.
                if(mGetLED_1() == mGetLED_2())
                {
                    mLED_1_Toggle();
                    mLED_2_Toggle();
                }
                else
                {
                    mLED_1_On();
                    mLED_2_On();
                }
                break;
            case 0x81:  //Get push button state command from PC application.
                INPacket[0] = 0x81;				//Echo back to the host PC the command we are fulfilling in the first byte.  In this case, the Get Pushbutton State command.
//				if(sw2 == 1)					//pushbutton not pressed, pull up resistor on circuit board is pulling the PORT pin high
				if (UserSW == 1)
				{
					INPacket[1] = 0x01;			
				}
				else							//sw2 must be == 0, pushbutton is pressed and overpowering the pull up resistor
				{
					INPacket[1] = 0x00;
				}				
				//Now check to make sure no previous attempts to send data to the host are still pending.  If any attemps are still
				//pending, we do not want to write to the endpoint 1 IN buffer again, until the previous transaction is complete.
				//Otherwise the unsent data waiting in the buffer will get overwritten and will result in unexpected behavior.    
                if(!USBHandleBusy(USBGenericInHandle))		
	            {	
		            //The endpoint was not "busy", therefore it is safe to write to the buffer and arm the endpoint.					
	                //The USBGenWrite() function call "arms" the endpoint (and makes the handle indicate the endpoint is busy).
	                //Once armed, the data will be automatically sent to the host (in hardware by the SIE) the next time the 
	                //host polls the endpoint.  Once the data is successfully sent, the handle (in this case USBGenericInHandle) 
	                //will indicate the the endpoint is no longer busy.
					USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,USBGEN_EP_SIZE);	
                }
                break;
        }
        
        //Re-arm the OUT endpoint for the next packet:
	    //The USBGenRead() function call "arms" the endpoint (and makes it "busy").  If the endpoint is armed, the SIE will 
	    //automatically accept data from the host, if the host tries to send a packet of data to the endpoint.  Once a data 
	    //packet addressed to this endpoint is received from the host, the endpoint will no longer be busy, and the application
	    //can read the data which will be sitting in the buffer.
        USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
    }
}//end ProcessIO
Exemple #21
0
/******************************************************************************
 * Function:        void ProcessIO(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function is a place holder for other user routines.
 *                  It is a mixture of both USB and non-USB tasks.
 *
 * Note:            None
 *****************************************************************************/
void USBUpdate(void) {
  byte data[2];
  byte i;
  byte paramNum;
  ulong tempLong;
  
  USBDeviceTasks();
  
  if ((USBDeviceState < CONFIGURED_STATE) || (USBSuspendControl==1)) {
    return;
  }

  //As the device completes the enumeration process, the USBCBInitEP() function will
  //get called.  In this function, we initialize the user application endpoints (in this
  //example code, the user application makes use of endpoint 1 IN and endpoint 1 OUT).
  //The USBGenRead() function call in the USBCBInitEP() function initializes endpoint 1 OUT
  //and "arms" it so that it can receive a packet of data from the host.  Once the endpoint
  //has been armed, the host can then send data to it (assuming some kind of application software
  //is running on the host, and the application software tries to send data to the USB device).

  //If the host sends a packet of data to the endpoint 1 OUT buffer, the hardware of the SIE will
  //automatically receive it and store the data at the memory location pointed to when we called
  //USBGenRead().  Additionally, the endpoint handle (in this case USBGenericOutHandle) will indicate
  //that the endpoint is no longer busy.  At this point, it is safe for this firmware to begin reading
  //from the endpoint buffer, and processing the data.  In this example, we have implemented a few very
  //simple commands.  For example, if the host sends a packet of data to the endpoint 1 OUT buffer, with the
  //first byte = 0x80, this is being used as a command to indicate that the firmware should "Toggle LED(s)".
  if(!USBHandleBusy(USBGenericOutHandle) && //Check if the endpoint has received any data from the host.
	  //Now check to make sure no previous attempts to send data to the host are still pending.  If any attemps are still
    //pending, we do not want to write to the endpoint 1 IN buffer again, until the previous transaction is complete.
    //Otherwise the unsent data waiting in the buffer will get overwritten and will result in unexpected behavior.
     (!USBGenericInHandle || !USBHandleBusy(USBGenericInHandle))) {
    if (OUTPacket[USB_PACKET_LEN] < 7) {
      // message too short
    }
    else {
      usbActivityTimeout = 3000; // reset timeout (in ms) 3 seconds
      
      switch(OUTPacket[USB_PACKET_CMD]) {				//Data arrived, check what kind of command might be in the packet of data.
      case USB_CMD_NULL:        // 0x00
        if (OUTPacket[USB_PACKET_LEN] != 7) {
          data[0] = USB_ERR_BAD_LEN;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else {
          UsbSendResp(USB_RESP_NULL, data);
        }  
        break;

      case USB_CMD_GET_VSTRING:
        if (OUTPacket[USB_PACKET_LEN] != 7) {
          data[0] = USB_ERR_BAD_LEN;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else {
          UsbSendResp(USB_RESP_GET_VSTRING, data);
        }  
        break;
        
      case USB_CMD_GET_CHAN:
        if (OUTPacket[USB_PACKET_LEN] != 7) {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else if (OUTPacket[USB_PACKET_STR] >= NUM_STRINGS) {
          data[0] = USB_ERR_BAD_PRM;
          data[1] = 0;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else if (!OUTPacket[USB_PACKET_MCT] || OUTPacket[USB_PACKET_MCT] > NUM_MCT) {
          data[0] = USB_ERR_BAD_PRM;
          data[1] = 1;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else {
          UsbSendResp(USB_RESP_GET_CHAN, data);
        }
        break;

      case USB_CMD_GET_MIRRORS:
        if (OUTPacket[USB_PACKET_LEN] != 7) {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else if (OUTPacket[USB_PACKET_STR] >= NUM_STRINGS) {
          data[0] = USB_ERR_BAD_PRM;
          data[1] = 0;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else if (!OUTPacket[USB_PACKET_MCT] || OUTPacket[USB_PACKET_MCT] > NUM_MCT) {
          data[0] = USB_ERR_BAD_PRM;
          data[1] = 1;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else {
          UsbSendResp(USB_RESP_GET_MIRRORS, data);
        }
        break;

      case USB_CMD_GET_STRING:
        if (OUTPacket[USB_PACKET_LEN] != 7) {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else if (OUTPacket[USB_PACKET_STR] >= NUM_STRINGS) {
          data[0] = USB_ERR_BAD_PRM;
          data[1] = 0;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        else {
          UsbSendResp(USB_RESP_GET_STRING, data);
        }
        break;

      case USB_CMD_FIELD_STATE:
        if (OUTPacket[USB_PACKET_LEN] == 7) {
          UsbSendResp(USB_RESP_FIELD_STATE, data);
        }  
        else if (OUTPacket[USB_PACKET_LEN] == 8) {
          FieldNewState(OUTPacket[USB_PACKET_DATA]);
          UsbSendResp(USB_RESP_FIELD_STATE, data);
        }  
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;

      case USB_CMD_GET_FCE:
        if (OUTPacket[USB_PACKET_LEN] == 7) {
          UsbSendResp(USB_RESP_GET_FCE, data);
        }  
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;
      
      case USB_CMD_GET_RTU:
        if (OUTPacket[USB_PACKET_LEN] == 7) {
          UsbSendResp(USB_RESP_GET_RTU, data);
        }  
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;

      case USB_CMD_SEND_MCT485:  // 0x64
        if (OUTPacket[USB_PACKET_LEN] >= 11
            && OUTPacket[USB_PACKET_LEN] <  MCT485_MAX_INDEX + 7) {
          //Mct485CannedMsg(MSG_ORIGIN_USB,
          //               OUTPacket[USB_PACKET_STR],
          //               OUTPacket[USB_PACKET_LEN]-7,
          //               &OUTPacket[USB_PACKET_DATA]);
          usb485TxString = OUTPacket[USB_PACKET_STR];
          usb485TxLen = OUTPacket[USB_PACKET_LEN]-7;
          for (i = 0; i < usb485TxLen; i++) {
            usb485TxBuffer[i] = OUTPacket[USB_PACKET_DATA+i];
          }
          // clear 485 response buffer
          usb485RxLen = 0;
          UsbSendResp(USB_RESP_SEND_MCT485, data);
        }  
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;

      case USB_CMD_GET_MCT485:   // 0x65
        if (OUTPacket[USB_PACKET_LEN] == 7) {
          UsbSendResp(USB_RESP_GET_MCT485, data);
        }  
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;
      
      case USB_CMD_RTC:         // 0x66
        if (OUTPacket[USB_PACKET_LEN] == 7) {
          UsbSendResp(USB_RESP_RTC, data);
        }
        else if (OUTPacket[USB_PACKET_LEN] == 13) {
          RtcSetClock(&OUTPacket[USB_PACKET_DATA]);
          UsbSendResp(USB_RESP_RTC, data);
        }
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;
      
      case USB_CMD_LOG:        // 0x67
        if (OUTPacket[USB_PACKET_LEN] == 7) {
          UsbSendResp(USB_RESP_LOG, data);
        }
        else if (OUTPacket[USB_PACKET_LEN] == 8) {
          if (OUTPacket[USB_PACKET_DATA] == 0) {
            DataLogFindFirstEntry();
          }
          else if (OUTPacket[USB_PACKET_DATA] == 0xFF) {  
            DataLogErase();
          }
          UsbSendResp(USB_RESP_LOG, data);
        }
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;
      
      case USB_CMD_DESICCANT:   // 0x68
        if (OUTPacket[USB_PACKET_LEN] == 7) {
          UsbSendResp(USB_RESP_DESICCANT, data);
        }
        else if (OUTPacket[USB_PACKET_LEN] == 9) {
          // manual force dessicant to set of outputs or state
          DesiccantNewState(OUTPacket[USB_PACKET_DATA], OUTPacket[USB_PACKET_DATA+1]);
          UsbSendResp(USB_RESP_DESICCANT, data);
        }  
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;
      
      case USB_CMD_SFC_PARAM:  // 0x69
        if (OUTPacket[USB_PACKET_LEN] == 8) {
          UsbSendResp(USB_RESP_SFC_PARAM, data);
        }
        else if (OUTPacket[USB_PACKET_LEN] > 8 && !(OUTPacket[USB_PACKET_LEN] & 0x03)) {
          // process one param at a time, prevents I2C queue entry overflow and avoids
          // I2C page boundary problems
          paramNum = OUTPacket[USB_PACKET_DATA];
          i = USB_PACKET_DATA+1;
          while (i < OUTPacket[USB_PACKET_LEN]-2) {
            tempLong = OUTPacket[i++];
            tempLong *= 256;
            tempLong += OUTPacket[i++];
            tempLong *= 256;
            tempLong += OUTPacket[i++];
            tempLong *= 256;
            tempLong += OUTPacket[i++];
            ParamWrite(paramNum, tempLong);
            paramNum++;
          }
          UsbSendResp(USB_RESP_SFC_PARAM, data);
        }  
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;
      
      case USB_CMD_MEMORY:     // 0x6A
        if (OUTPacket[USB_PACKET_LEN] == 11) {
          data[4] = 16;
          UsbSendResp(USB_RESP_MEMORY, data);
        }
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;
      
      case USB_CMD_TEST:      // 0x6B
        if (OUTPacket[USB_PACKET_LEN] == 8) {
          UsbSendResp(USB_RESP_TEST, data);
          for (tempLong = 0; tempLong < 1000000; tempLong++) {
          }
          if (OUTPacket[USB_PACKET_DATA] == 0x01) {
            Mct485Init();
          }
          else if (OUTPacket[USB_PACKET_DATA] == 0x02) {
            StringInit();
          }
          else if (OUTPacket[USB_PACKET_DATA] == 0x03) {
            FieldInit();
          }
          else if (OUTPacket[USB_PACKET_DATA] == 0x04) {
            SoftReset();
          }
        }
        else {
          data[0] = USB_ERR_BAD_LEN;
          data[1] = 7;
          UsbSendResp(USB_RESP_BAD_MSG, data);
        }
        break;
      } // switch (cmd)
    } // else process messages  

    //Re-arm the OUT endpoint for the next packet:
	  //The USBGenRead() function call "arms" the endpoint (and makes it "busy").  If the endpoint is armed, the SIE will
	  //automatically accept data from the host, if the host tries to send a packet of data to the endpoint.  Once a data
	  //packet addressed to this endpoint is received from the host, the endpoint will no longer be busy, and the application
	  //can read the data which will be sitting in the buffer.
    USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
  } // if
}// UsbUpdate()
Exemple #22
0
BOOL midiTxHandleBusy(void)
{
    return USBHandleBusy(midiTxHandle);
}
BYTE MSDReadHandler(void)
{
    static BYTE MSDReadState = MSD_READ10_WAIT;
    
    switch(MSDReadState)
    {
        case MSD_READ10_WAIT:
        	LBA.v[3]=gblCBW.CBWCB[2];
        	LBA.v[2]=gblCBW.CBWCB[3];
        	LBA.v[1]=gblCBW.CBWCB[4];
        	LBA.v[0]=gblCBW.CBWCB[5];
        	
        	TransferLength.v[1]=gblCBW.CBWCB[7];
        	TransferLength.v[0]=gblCBW.CBWCB[8];
        	
        	msd_csw.bCSWStatus=0x0;
        	msd_csw.dCSWDataResidue=0x0;
        	
            MSDReadState = MSD_READ10_BLOCK;
            //Fall through to MSD_READ_BLOCK
        case MSD_READ10_BLOCK:
            if(TransferLength.Val == 0)
            {
                MSDReadState = MSD_READ10_WAIT;
                break;
            }
            
            TransferLength.Val--;					// we have read 1 LBA
            MSDReadState = MSD_READ10_SECTOR;
            //Fall through to MSD_READ10_SECTOR
        case MSD_READ10_SECTOR:
            //if the old data isn't completely sent yet
            if(USBHandleBusy(USBMSDInHandle) != 0)
            {
                break;
            }

    		if(LUNSectorRead(LBA.Val, (BYTE*)&msd_buffer[0]) != TRUE)
    		{
				msd_csw.bCSWStatus=0x01;			// Error 0x01 Refer page#18
                                                    // of BOT specifications
				/* Don't read any more data*/
				msd_csw.dCSWDataResidue=0x0;
              
                MSD_State = MSD_DATA_IN;
        		break;
            }

            LBA.Val++;
            
			msd_csw.bCSWStatus=0x00;			// success
			msd_csw.dCSWDataResidue=BLOCKLEN_512;//in order to send the
                                                 //512 bytes of data read
                                                 
            ptrNextData=(BYTE *)&msd_buffer[0];
            
            MSDReadState = MSD_READ10_TX_SECTOR;
    
            //Fall through to MSD_READ10_TX_SECTOR
        case MSD_READ10_TX_SECTOR:
            if(msd_csw.dCSWDataResidue == 0)
            {
                MSDReadState = MSD_READ10_BLOCK;
                break;
            }
            
            MSDReadState = MSD_READ10_TX_PACKET;
            //Fall through to MSD_READ10_TX_PACKET
            
        case MSD_READ10_TX_PACKET:
        	if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue>=MSD_IN_EP_SIZE)) 
            {
        		/* Write next chunk of data to EP Buffer and send */
                if(USBHandleBusy(USBMSDInHandle))
                {
                    break;
                }
                
                USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,ptrNextData,MSD_IN_EP_SIZE);
                
  			    MSDReadState = MSD_READ10_TX_SECTOR;

        		gblCBW.dCBWDataTransferLength-=	MSD_IN_EP_SIZE;
        		msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE;
        		ptrNextData+=MSD_IN_EP_SIZE;
        	}
            break;
    }
    
    return MSDReadState;
}
Exemple #24
0
/********************************************************************
 * Function:        void ProcessIO(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function is a place holder for other user
 *                  routines. It is a mixture of both USB and
 *                  non-USB tasks.
 *
 * Note:            None
 *******************************************************************/
void ProcessIO(void)
{

    // User Application USB tasks
    if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return;

	

    if(!USBHandleBusy(USBRxHandle))
    {
        //We have received a MIDI packet from the host, process it and then
        //  prepare to receive the next packet

        //INSERT MIDI PROCESSING CODE HERE

		BOOL note_stealing = FALSE;
		static BYTE note;
		int channel;
		BYTE oldest_channel;
		unsigned long lowest_counter;
		BOOL duplicate_note = FALSE;
		float bent_note;
		unsigned char bend_value;

		USB_AUDIO_MIDI_EVENT_PACKET *packet = ReceivedDataBuffer; // suspicious pointer conversion, yada yada
	
		// run through the complete buffer (16 packets x 4 bytes) and process MIDI messages
		int buffer = 16; while(buffer--)
		{
			switch(packet->DATA_0 & MIDI_MESSAGE_MASK)
			{
				case MIDI_NOTE_ON:

					if(note_stealing)
					{
						// Note stealing logic: find the channel with the lowest steal counter,
						// and reassign it to the newest note on command. In the event of a
						// tie, channel order decides.
	
						oldest_channel = 0;
						lowest_counter = 0xFFFFFFFF;
	
						note = packet->DATA_1;
						
						channel = CHANNELS;
						while(channel--)
						{
							if(Generator[channel].Active == TRUE)
								Generator[channel].StealTimer--;
	
							if(Generator[channel].MidiNote == note && Generator[channel].Active == TRUE)
								duplicate_note = TRUE;
	
							if(Generator[channel].StealTimer < lowest_counter)
							{
								lowest_counter = Generator[channel].StealTimer;
								oldest_channel = channel;
							}
						}
	
						if(!duplicate_note)
						{
							Generator[oldest_channel].MidiNote = note;
							Generator[oldest_channel].Period = NotePeriod[note];
							Generator[oldest_channel].StealTimer = 0xFFFFFFFF;
							Generator[oldest_channel].Active = TRUE;
						}
					}
					else
					{
						note = packet->DATA_1;
						channel = packet->DATA_0 & MIDI_CHANNEL_MASK;

						if(channel >= 0 && channel < CHANNELS)
						{
							Generator[channel].MidiNote = note;
							Generator[channel].Period = NotePeriod[note];
							Generator[channel].Active = TRUE;
						}
					}

					break;
				
				case MIDI_NOTE_OFF:

					if(note_stealing)
					{
						channel = CHANNELS;
		
						note = packet->DATA_1;
		
						// find the active channel for this note, if it exists
						while(channel--)
						{
							if(Generator[channel].MidiNote == note)
							{
								//kill it
								Generator[channel].Active = FALSE;
								Generator[channel].StealTimer = 0;
								break;
							}
						}
					}
					else
					{
						note = packet->DATA_1;
						channel = packet->DATA_0 & MIDI_CHANNEL_MASK;

						if(channel >= 0 && channel < CHANNELS)
						{
							if(Generator[channel].MidiNote == note)
							{
								Generator[channel].Active = FALSE;
							}
						}
					}

					break;

				// Please excuse this atrocious bend code. It was rushed to be used, only to not
				// actually be used at all due to a change in song choice. It did work "kind of"
				// when I originally implemented it, but I never ironed the bugs out. In fact it
				// may not work at all in its present state due to changes elsewhere. I definitely
				// did have it working at one point in time for a song demo I decided not to make.

				case MIDI_PITCH_BEND:
					{
						channel = packet->DATA_0 & MIDI_CHANNEL_MASK;
						

						if(channel >= 0 && channel < CHANNELS)
						{
							note = Generator[channel].MidiNote;
							//bent_note = NotePeriod[note];

							// 100 cents per semitone, PITCH_BEND_RANGE max semitones

							// 1. calculate how many cents to bend pitch ...

							// we can use a piecewise linear interpolation between semitones
							// if we restrict the max bend range to +/- 2 semitones, we can
							// just check if the bend is between 0 and 1 semitones and linearly interpolate,
							// or if it's between 1 and 2 semitones, start at the next highest note, and linearly
							// interpolate to the one above that (or so on for successively higher ranges)

							// 2 ^ 1/12 = 1.05946309435929526456...
							// 2 ^-1/12 = 0.94387431268169349664...

							// for PITCH_BEND_RANGE = 2
							// max cents = PITCH_BEND_RANGE * 100 = 200 cents
							// 0x2000 - 0x3FFF = 200 cents; 0x2000 - 0x0000 = 200 cents

							// 0x2000 = no bend, 0x0000 = full bend down, 0x3FFF = full bend up


							// 1. assemble the 14-bit bend value
							//bend_value = ((int)(Generator[channel].DATA_2 & 0x7F) << 7) | (int)(Generator[channel].DATA_1 & 0x7F);

							// actually, we can probably get away with using only the most significant byte because the floppy-stepper-oscillator is such a crude sound in the first place
							bend_value = packet->DATA_2;

							
							
							// 2. determine if the bend is up or down
							if(bend_value > 0x40)
							{
								bend_value -= 0x40; // value between 0x00 and 0x3F

								if(bend_value >= 0x20) // bend past +1 semitone
								{
									bend_value -= 0x20; // value between 0x00 and 0x1F;
									bent_note = NotePeriod[note+1];
								}
								else // bend between 0 and +1 semitone
								{
									bent_note = NotePeriod[note];
								}

								// !! FIX THIS
								// !! we need to bend the cycle period down to bend frequency up, and vice-versa

								//bend_value = 0x20 - bend_value;
								bent_note *= BendCoeff[bend_value];
							}
							else if(bend_value < 0x40)
							{
								bend_value = bend_value - 0x39;
							}

							Generator[channel].Period = bent_note;
						}
					}

					break;

				default:
					break;
			}
	
			packet++;
		}

        //Get ready for next packet (this will overwrite the old data)
        USBRxHandle = USBRxOnePacket(MIDI_EP,(BYTE*)&ReceivedDataBuffer,64);
    }

}//end ProcessIO
/******************************************************************************
 	Function:
 		BYTE MSDWriteHandler(void)
 		
 	Description:
 		This funtion processes a write command received through 
 		the MSD class driver
 		
 	PreCondition:
 		None
 		
 	Parameters:
 		None
 		
 	Return Values:
 		BYTE - the current state of the MSDWriteHandler state
 		machine.  The valid values are defined in MSD.h under the 
 		MSDWriteHandler state machine declaration section
 		
 	Remarks:
 		None
 
 *****************************************************************************/
BYTE MSDWriteHandler(void)
{
    static BYTE MSDWriteState = MSD_WRITE10_WAIT;
    
    switch(MSDWriteState)
    {
        case MSD_WRITE10_WAIT:
         	/* Read the LBA, TransferLength fields from Command Block
               NOTE: CB is Big-Endian */
        
        	LBA.v[3]=gblCBW.CBWCB[2];
        	LBA.v[2]=gblCBW.CBWCB[3];
        	LBA.v[1]=gblCBW.CBWCB[4];
        	LBA.v[0]=gblCBW.CBWCB[5];
        	TransferLength.v[1]=gblCBW.CBWCB[7];
        	TransferLength.v[0]=gblCBW.CBWCB[8];
        
        	msd_csw.bCSWStatus=0x0;	
        	
        	MSD_State = MSD_WRITE10_BLOCK;
        	//Fall through to MSD_WRITE10_BLOCK
        case MSD_WRITE10_BLOCK:
            if(TransferLength.Val == 0)
            {
                MSDWriteState = MSD_WRITE10_WAIT;
                break;
            }
            
            MSDWriteState = MSD_WRITE10_RX_SECTOR;
            ptrNextData=(BYTE *)&msd_buffer[0];
              
        	msd_csw.dCSWDataResidue=BLOCKLEN_512;
        	
            //Fall through to MSD_WRITE10_RX_SECTOR
        case MSD_WRITE10_RX_SECTOR:
        {
      		/* Read 512B into msd_buffer*/
      		if(msd_csw.dCSWDataResidue>0) 
      		{
                if(USBHandleBusy(USBMSDOutHandle) == TRUE)
                {
                    break;
                }

                USBMSDOutHandle = USBRxOnePacket(MSD_DATA_OUT_EP,ptrNextData,MSD_OUT_EP_SIZE);
                MSDWriteState = MSD_WRITE10_RX_PACKET;
                //Fall through to MSD_WRITE10_RX_PACKET
      	    }
      	    else
      	    {
          		if(LUNWriteProtectState()) 
                {
              	    gblSenseData[LUN_INDEX].SenseKey=S_NOT_READY;
              	    gblSenseData[LUN_INDEX].ASC=ASC_WRITE_PROTECTED;
              	    gblSenseData[LUN_INDEX].ASCQ=ASCQ_WRITE_PROTECTED;
              	    msd_csw.bCSWStatus=0x01;
              	    //TODO: (DF) - what state should I return to?
              	}
              	else
              	{
      			    MSDWriteState = MSD_WRITE10_SECTOR;     
      			}
      			break;
          	}
        }
        //Fall through to MSD_WRITE10_RX_PACKET
        case MSD_WRITE10_RX_PACKET:
            if(USBHandleBusy(USBMSDOutHandle) == TRUE)
            {
                break;
            }
            
        	gblCBW.dCBWDataTransferLength-=USBHandleGetLength(USBMSDOutHandle);		// 64B read
        	msd_csw.dCSWDataResidue-=USBHandleGetLength(USBMSDOutHandle);
            ptrNextData += MSD_OUT_EP_SIZE;
            
            MSDWriteState = MSD_WRITE10_RX_SECTOR;
            break;
        case MSD_WRITE10_SECTOR:
        {
      		if(LUNSectorWrite(LBA.Val, (BYTE*)&msd_buffer[0], (LBA.Val==0)?TRUE:FALSE) != TRUE)
      		{
          		break;
      		}
      
    //		if (status) {
    //			msd_csw.bCSWStatus=0x01;
    //			/* add some sense keys here*/
    //		}
      
      		LBA.Val++;				// One LBA is written. Write the next LBA
      		TransferLength.Val--;
      
            MSDWriteState = MSD_WRITE10_BLOCK;
            break;
        } 
    }
    
    return MSDWriteState;
}
Exemple #26
0
static void processUsbCommands(void)
{
#if defined(USB_POLLING)
    // Check bus status and service USB interrupts.
    USBDeviceTasks(); // Interrupt or polling method.  If using polling, must call
    // this function periodically.  This function will take care
    // of processing and responding to SETUP transactions
    // (such as during the enumeration process when you first
    // plug in).  USB hosts require that USB devices should accept
    // and process SETUP packets in a timely fashion.  Therefore,
    // when using polling, this function should be called
    // regularly (such as once every 1.8ms or faster** [see
    // inline code comments in usb_device.c for explanation when
    // "or faster" applies])  In most cases, the USBDeviceTasks()
    // function does not take very long to execute (ex: <100
    // instruction cycles) before it returns.
#endif

    // Note: The user application should not begin attempting to read/write over the USB
    // until after the device has been fully enumerated.  After the device is fully
    // enumerated, the USBDeviceState will be set to "CONFIGURED_STATE".
    if ((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1))
        return;

    // As the device completes the enumeration process, the UsbCbInitEP() function will
    // get called.  In this function, we initialize the user application endpoints (in this
    // example code, the user application makes use of endpoint 1 IN and endpoint 1 OUT).
    // The USBGenRead() function call in the UsbCbInitEP() function initializes endpoint 1 OUT
    // and "arms" it so that it can receive a packet of data from the host.  Once the endpoint
    // has been armed, the host can then send data to it (assuming some kind of application software
    // is running on the host, and the application software tries to send data to the USB device).

    // If the host sends a packet of data to the endpoint 1 OUT buffer, the hardware of the SIE will
    // automatically receive it and store the data at the memory location pointed to when we called
    // USBGenRead().  Additionally, the endpoint handle (in this case UsbOutCmdHandle) will indicate
    // that the endpoint is no longer busy.  At this point, it is safe for this firmware to begin reading
    // from the endpoint buffer, and processing the data.  In this example, we have implemented a few very
    // simple commands.  For example, if the host sends a packet of data to the endpoint 1 OUT buffer, with the
    // first byte = 0x80, this is being used as a command to indicate that the firmware should "Toggle LED(s)".
    if (!USBHandleBusy(UsbOutCmdHandle)) { // Check if the endpoint has received any data from the host.
#if DEBUG
        unsigned char l = USBHandleGetLength(UsbOutCmdHandle);

        if (usbfifo_debug_operation.dump_usb_out == 1) {
            unsigned char b[16];
            unsigned char i;
            putrsUSART("USB OUT: '");
            for (i=0;i<l;++i) {
                if (i != 0) {
                    while (BusyUSART());
                    putcUSART(' ');
                }
                sprintf(b, "%02x", OutCmdPacket[i]);
                putsUSART(b);
            }
            sprintf(b, "' len=%3d\r\n", l);
            putsUSART(b);
        }

        if (usbfifo_debug_operation.usb_loopback == 1) {
            unsigned char i;
            // Now check to make sure no previous attempts to send data to the host are still pending.  If any attemps are still
            // pending, we do not want to write to the endpoint 1 IN buffer again, until the previous transaction is complete.
            // Otherwise the unsent data waiting in the buffer will get overwritten and will result in unexpected behavior.
            while (USBHandleBusy(UsbInCmdHandle));

            for (i=0;i<l;++i)
                InCmdPacket[i] = OutCmdPacket[i];

            // The endpoint was not "busy", therefore it is safe to write to the buffer and arm the endpoint.
            // The USBGenWrite() function call "arms" the endpoint (and makes the handle indicate the endpoint is busy).
            // Once armed, the data will be automatically sent to the host (in hardware by the SIE) the next time the
            // host polls the endpoint.  Once the data is successfully sent, the handle (in this case UsbInCmdHandle)
            // will indicate the the endpoint is no longer busy.
            UsbInCmdHandle = USBGenWrite(USBGEN_CMD_EP_NUM, (BYTE*)&InCmdPacket, l);
        }
#endif

        switch (OutCmdPacket[0]) {
#if DEBUG
            case USBFIFO_CMD_DUMP_USB_OUT:
                usbfifo_debug_operation.dump_usb_out ^= 1;
                break;
            case USBFIFO_CMD_DUMP_FIFO_OUT:
                usbfifo_debug_operation.dump_fifo_out ^= 1;
                break;
            case USBFIFO_CMD_FIFO_LOOPBACK:
                usbfifo_debug_operation.fifo_loopback ^= 1;
                break;
            case USBFIFO_CMD_USB_LOOPBACK:
                usbfifo_debug_operation.usb_loopback ^= 1;
                break;
#endif
            default:
                {
                    unsigned char b[8];
                    putrsUSART("Unexpected cmd=");
                    sprintf(b, "0x%2X\r\n", OutCmdPacket[0]);
                    putsUSART(b);
                }
                break;
        }

        // Re-arm the OUT endpoint for the next packet:
        // The USBGenRead() function call "arms" the endpoint (and makes it "busy").  If the endpoint is armed, the SIE will
        // automatically accept data from the host, if the host tries to send a packet of data to the endpoint.  Once a data
        // packet addressed to this endpoint is received from the host, the endpoint will no longer be busy, and the application
        // can read the data which will be sitting in the buffer.
        UsbOutCmdHandle = USBGenRead(USBGEN_CMD_EP_NUM, (BYTE*)&OutCmdPacket, USBGEN_EP_SIZE);
    }

    if (!USBHandleBusy(UsbOutDataHandle)) {
#if USBGEN_EP_SIZE > FIFO_9403A_MAX_MSG_LEN
#error "Transfer of more than FIFO_9403A_MAX_MSG_LEN not implemented"
#endif
        unsigned char l = USBHandleGetLength(UsbOutDataHandle);
        unsigned char i;

#if DEBUG
        if (usbfifo_debug_operation.dump_usb_out == 1) {
            unsigned char b[16];
            putrsUSART("USB OUT: '");
            for (i=0;i<l;++i) {
                if (i != 0) {
                    while (BusyUSART());
                    putcUSART(' ');
                }
                sprintf(b, "%02x", OutDataPacket[i]);
            }
            sprintf(b, "' len=%3d\r\n", l);
            putsUSART(b);
        }

        if (usbfifo_debug_operation.usb_loopback == 1) {
            while (USBHandleBusy(UsbInDataHandle)); // ensure that FIFO data left the device

            for (i=0;i<l;++i)
                InDataPacket[i] = OutDataPacket[i];

            /* FIXME: use real ping-pong */
            UsbInDataHandle = USBGenWrite(USBGEN_DATA_EP_NUM, (BYTE*)&InDataPacket, l);
            while (USBHandleBusy(UsbInDataHandle)); // have to wait here as full ping-pong is not implemented
                                                    // and thus we don't want data from FIFO override the data being sent here
        }
#endif

        fifo9403aPush(l, 1);
        for (i=0;i<l;++i)
            fifo9403aPush(OutDataPacket[i], 1);

        UsbOutDataHandle = USBGenRead(USBGEN_DATA_EP_NUM, (BYTE*)&OutDataPacket, USBGEN_EP_SIZE);
    }
}
void USBCCIDBulkInService(void)
{
    WORD byte_to_send;
    BYTE i;

    USBMaskInterrupts();
    if(USBHandleBusy(usbCcidBulkInHandle)) 
    {
        USBUnmaskInterrupts();
        return;
    }


    if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_COMPLETING)
        usbCcidBulkInTrfState = USB_CCID_BULK_IN_READY;
    
    /*
     * If USB_CCID_BULK_IN_READY state, nothing to do, just return.
     */
    if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_READY)
    {
        USBUnmaskInterrupts();
        return;
    }
    
    /*
     * If USB_CCID_BULK_IN_BUSY_ZLP state, send zero length packet
     */
    if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_BUSY_ZLP)
    {
        usbCcidBulkInHandle = USBTxOnePacket(USB_EP_BULK_IN,NULL,0);
        usbCcidBulkInTrfState = USB_CCID_BULK_IN_COMPLETING;
    }
    else if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_BUSY) 
    {
        /*
         * First, have to figure out how many byte of data to send.
         */
    	if(usbCcidBulkInLen > sizeof(usbCcidBulkInEndpoint)) 
    	    byte_to_send = sizeof(usbCcidBulkInEndpoint);
    	else
    	    byte_to_send = usbCcidBulkInLen;
            
        /*
         * Subtract the number of bytes just about to be sent from the total.
         */
    	usbCcidBulkInLen = usbCcidBulkInLen - byte_to_send;
    	  
        pCCIDDst.bRam = (BYTE*)usbCcidBulkInEndpoint; // Set destination pointer
        
        i = byte_to_send;
       
        while(i)
        {
            *pCCIDDst.bRam = *pCCIDSrc.bRam;
            pCCIDDst.bRam++;
            pCCIDSrc.bRam++;
            i--;
        }//end while(byte_to_send._word)
 
        
        /*
         * Lastly, determine if a zero length packet state is necessary.
         * See explanation in USB Specification 2.0: Section 5.8.3
         */
        if(usbCcidBulkInLen == 0)
        {
            if(byte_to_send == USB_EP_SIZE)
                usbCcidBulkInTrfState = USB_CCID_BULK_IN_BUSY_ZLP;
            else
                usbCcidBulkInTrfState = USB_CCID_BULK_IN_COMPLETING;
        }//end if(usbCcidBulkInLen...)
        usbCcidBulkInHandle = USBTxOnePacket(USB_EP_BULK_IN,(BYTE*)usbCcidBulkInEndpoint,byte_to_send);

    }//end if(cdc_tx_sate == USB_CCID_BULK_IN_BUSY)
    USBUnmaskInterrupts();
}//end USBCCIDBulkInService
Exemple #28
0
/******************************************************************************
 * Function:        void ServiceRequests(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    USB traffic can be generated
 *
 * Overview:        This function takes in the commands from the PC from the
 *                  application and executes the commands requested
 *
 * Note:            None
 *****************************************************************************/
void ServiceRequests(void)
{
    BYTE index;
    
    //Check to see if data has arrived
    if(!USBHandleBusy(USBGenericOutHandle))
    {        
        //if the handle is no longer busy then the last
        //transmission is complete
       
        counter = 0;

        INPacket.CMD=OUTPacket.CMD;
        INPacket.len=OUTPacket.len;

        //process the command
        switch(OUTPacket.CMD)
        {
            case READ_VERSION:
                //dataPacket._byte[1] is len
                INPacket._byte[2] = MINOR_VERSION;
                INPacket._byte[3] = MAJOR_VERSION;
                counter=0x04;
                break;

            case ID_BOARD:
                counter = 0x01;
                if(OUTPacket.ID == 0)
                {
                    mLED_3_Off();mLED_4_Off();
                }
                else if(OUTPacket.ID == 1)
                {
                    mLED_3_Off();mLED_4_On();
                }
                else if(OUTPacket.ID == 2)
                {
                    mLED_3_On();mLED_4_Off();
                }
                else if(OUTPacket.ID == 3)
                {
                    mLED_3_On();mLED_4_On();
                }
                else
                    counter = 0x00;
                break;

            case UPDATE_LED:
                #if defined(PIC18F87J50_PIM) || defined(PIC18F46J50_PIM) || defined(PIC18F47J53_PIM)
                    blinkStatusValid = FALSE;
                #endif
                // LED1 & LED2 are used as USB event indicators.
                if(OUTPacket.led_num == 3)
                {
                    if(OUTPacket.led_status)
                    {
                        mLED_3_On(); 
                    }
                    else
                    {
                        mLED_3_Off();
                    }
                    counter = 0x01;
                }//end if
                else if(OUTPacket.led_num == 4)
                {
                    if(OUTPacket.led_status)
                    {
                        mLED_4_On(); 
                    }
                    else
                    {
                        mLED_4_Off();
                    }
                    counter = 0x01;
                }//end if else
                break;
                
            case SET_TEMP_REAL:
                temp_mode = TEMP_REAL_TIME;
                ResetTempLog();
                counter = 0x01;
                break;

            case RD_TEMP:
                if(AcquireTemperature())
                {
                    INPacket._byte[1] = temperature.v[0];
                    INPacket._byte[2] = temperature.v[1];
                    counter=0x03;
                }//end if

                break;

            case SET_TEMP_LOGGING:
                temp_mode = TEMP_LOGGING;
                ResetTempLog();
                counter=0x01;
                break;

            case RD_TEMP_LOGGING:
                counter = (valid_temp<<1)+2;  // Update count in byte
                INPacket.len = (valid_temp<<1);

                for(index = valid_temp; index > 0; index--)
                {
                    if(pTemp == 0)
                        pTemp = 29;
                    else
                        pTemp--;
                    INPacket._word[index] = temp_data[pTemp];
                }//end for
                
                ResetTempLog();             // Once read, log will restart
                break;

            case RD_POT:
                {
                    WORD_VAL w;

                    mInitPOT();
                    w = ReadPOT();

                    INPacket._byte[1] = w.v[0];
                    INPacket._byte[2] = w.v[1];

                    counter=0x03;
                }
                break;
                
            case RESET:
                Reset();
                break;
                
            default:
                break;
        }//end switch()
        if(counter != 0)
        {
            if(!USBHandleBusy(USBGenericInHandle))
            {
                USBGenericInHandle = USBGenWrite(USBGEN_EP_NUM,(BYTE*)&INPacket,counter);
            }
        }//end if
        
        //Re-arm the OUT endpoint for the next packet
        USBGenericOutHandle = USBGenRead(USBGEN_EP_NUM,(BYTE*)&OUTPacket,USBGEN_EP_SIZE);
    }//end if

}//end ServiceRequests
Exemple #29
0
void CDCTxService(void)
{
    BYTE byte_to_send;
    BYTE i;
    
    USBMaskInterrupts();
    
    CDCNotificationHandler();
    
    if(USBHandleBusy(CDCDataInHandle)) 
    {
        USBUnmaskInterrupts();
        return;
    }

    /*
     * Completing stage is necessary while [ mCDCUSartTxIsBusy()==1 ].
     * By having this stage, user can always check cdc_trf_state,
     * and not having to call mCDCUsartTxIsBusy() directly.
     */
    if(cdc_trf_state == CDC_TX_COMPLETING)
        cdc_trf_state = CDC_TX_READY;
    
    /*
     * If CDC_TX_READY state, nothing to do, just return.
     */
    if(cdc_trf_state == CDC_TX_READY)
    {
        USBUnmaskInterrupts();
        return;
    }
    
    /*
     * If CDC_TX_BUSY_ZLP state, send zero length packet
     */
    if(cdc_trf_state == CDC_TX_BUSY_ZLP)
    {
        CDCDataInHandle = USBTxOnePacket(CDC_DATA_EP,NULL,0);
        //CDC_DATA_BD_IN.CNT = 0;
        cdc_trf_state = CDC_TX_COMPLETING;
    }
    else if(cdc_trf_state == CDC_TX_BUSY)
    {
        /*
         * First, have to figure out how many byte of data to send.
         */
    	if(cdc_tx_len > sizeof(cdc_data_tx))
    	    byte_to_send = sizeof(cdc_data_tx);
    	else
    	    byte_to_send = cdc_tx_len;

        /*
         * Subtract the number of bytes just about to be sent from the total.
         */
    	cdc_tx_len = cdc_tx_len - byte_to_send;
    	  
        pCDCDst.bRam = (BYTE*)&cdc_data_tx; // Set destination pointer
        
        i = byte_to_send;
        if(cdc_mem_type == USB_EP0_ROM)            // Determine type of memory source
        {
            while(i)
            {
                *pCDCDst.bRam = *pCDCSrc.bRom;
                pCDCDst.bRam++;
                pCDCSrc.bRom++;
                i--;
            }//end while(byte_to_send)
        }
        else // _RAM
        {
            while(i)
            {
                *pCDCDst.bRam = *pCDCSrc.bRam;
                pCDCDst.bRam++;
                pCDCSrc.bRam++;
                i--;
            }//end while(byte_to_send._word)
        }//end if(cdc_mem_type...)
        
        /*
         * Lastly, determine if a zero length packet state is necessary.
         * See explanation in USB Specification 2.0: Section 5.8.3
         */
        if(cdc_tx_len == 0)
        {
            if(byte_to_send == CDC_DATA_IN_EP_SIZE)
                cdc_trf_state = CDC_TX_BUSY_ZLP;
            else
                cdc_trf_state = CDC_TX_COMPLETING;
        }//end if(cdc_tx_len...)
        CDCDataInHandle = USBTxOnePacket(CDC_DATA_EP,(BYTE*)&cdc_data_tx,byte_to_send);

    }//end if(cdc_tx_sate == CDC_TX_BUSY)
    
    USBUnmaskInterrupts();
}//end CDCTxService
/*********************************************************************************
  Function:
        BYTE MSDTasks(void)
    
  Summary:
    This function runs the MSD class state machines and all of its
    sub-systems. This function should be called periodically once the
    device is in the configured state in order to keep the MSD state
    machine going.
  Description:
    This function runs the MSD class state machines and all of its
    sub-systems. This function should be called periodically once the
    device is in the configured state in order to keep the MSD state
    machine going.
    
    Typical Usage:
    <code>
    void main(void)
    {
        USBDeviceInit();
        while(1)
        {
            USBDeviceTasks();
            if((USBGetDeviceState() \< CONFIGURED_STATE) ||
               (USBIsDeviceSuspended() == TRUE))
            {
                //Either the device is not configured or we are suspended
                //  so we don't want to do execute any application code
                continue;   //go back to the top of the while loop
            }
            else
            {
                //Keep the MSD state machine going
                MSDTasks();
    
                //Run application code.
                UserApplication();
            }
        }
    }
    </code>
  Conditions:
    None
  Return Values:
    BYTE -  the current state of the MSD state machine the valid values are
            defined in MSD.h under the MSDTasks state machine declaration section.
            The possible values are the following\:
            * MSD_WAIT
            * MSD_DATA_IN
            * MSD_DATA_OUT
            * MSD_SEND_CSW
  Remarks:
    None                                                                          
  *********************************************************************************/	
BYTE MSDTasks(void)
{
    BYTE i;
    
    switch(MSD_State)
    {
        case MSD_WAIT:
        {
            //If the MSD state machine is waiting for something to happen
            if(!USBHandleBusy(USBMSDOutHandle))
            {
        		//If we received an OUT packet from the host
                //  then copy the data from the buffer to a global
                //  buffer so that we can keep the information but
                //  reuse the buffer
        		gblCBW.dCBWSignature=msd_cbw.dCBWSignature;					
        		gblCBW.dCBWTag=msd_cbw.dCBWTag;
        		gblCBW.dCBWDataTransferLength=msd_cbw.dCBWDataTransferLength;
            	gblCBW.bCBWFlags=msd_cbw.bCBWFlags;
            	gblCBW.bCBWLUN=msd_cbw.bCBWLUN;
        	    gblCBW.bCBWCBLength=msd_cbw.bCBWCBLength;		// 3 MSB are zero

            	for (i=0;i<msd_cbw.bCBWCBLength;i++)
            	{
            		gblCBW.CBWCB[i]=msd_cbw.CBWCB[i];
                }
            		
                gblCBWLength=USBHandleGetLength(USBMSDOutHandle);

        	    //If this CBW is valid?
        		if ((gblCBWLength==MSD_CBW_SIZE)&&(gblCBW.dCBWSignature==0x43425355)) 
            	{
                    //Is this CBW meaningful?	
       				if((gblCBW.bCBWLUN<=0x0f)
               		&&(gblCBW.bCBWCBLength<=0x10)
               		&&(gblCBW.bCBWCBLength>=0x01)
               		&&(gblCBW.bCBWFlags==0x00||gblCBW.bCBWFlags==0x80)) 
            		{
                		//Prepare the CSW to be sent
                    	msd_csw.dCSWTag=gblCBW.dCBWTag;
                    	msd_csw.dCSWSignature=0x53425355;
                    	
                    	//Keep track of retry attempts, in case of temporary failures
                    	//during processing of a command.
                    	MSDRetryAttempt = 0;
                    	
                    	//Check the command.  With the exception of the REQUEST_SENSE
                    	//command, we should reset the sense key info for each new command block.
                    	//Assume the command will get processed successfully (and hence "NO SENSE" 
                    	//response, which is used for success cases), unless handler code
                    	//later on detects some kind of error.  If it does, it should
                    	//update the sense keys to reflect the type of error detected,
                    	//prior to sending the CSW.
                    	if(gblCBW.CBWCB[0] != MSD_REQUEST_SENSE)
                    	{
                      		gblSenseData[LUN_INDEX].SenseKey=S_NO_SENSE;
        			        gblSenseData[LUN_INDEX].ASC=ASC_NO_ADDITIONAL_SENSE_INFORMATION;
        			        gblSenseData[LUN_INDEX].ASCQ=ASCQ_NO_ADDITIONAL_SENSE_INFORMATION;
    			        }
                    	
        				/* If direction is device to host*/
        				if (gblCBW.bCBWFlags==0x80)
        				{
        					MSD_State=MSD_DATA_IN;
        				}
        				else if (gblCBW.bCBWFlags==0x00) 
            			{
        					/* If direction is host to device*/
        					/* prepare to read data in msd_buffer */
            			    MSD_State=MSD_DATA_OUT;
        				}        								
        			}
        		}
            }
            break;
        }
        case MSD_DATA_IN:
            if(MSDProcessCommand() == MSD_COMMAND_WAIT)
            {
                // Done processing the command, send the status
                MSD_State = MSD_SEND_CSW;
            }
            break;
        case MSD_DATA_OUT:
            if(MSDProcessCommand() == MSD_COMMAND_WAIT)
            {
    			/* Finished receiving the data prepare and send the status */
    		  	if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue!=0)) 
    		  	{
    		  		msd_csw.bCSWStatus=0x02;
    		    }
                MSD_State = MSD_SEND_CSW;
            }
            break;
        case MSD_SEND_CSW:
            if(USBHandleBusy(USBMSDInHandle))
            {
                //The TX buffer is not ready to send the status yet.
                break;
            }
            
            USBMSDInHandle = USBTxOnePacket(MSD_DATA_IN_EP,(BYTE*)&msd_csw,MSD_CSW_SIZE);
            
            //Get ready for next command to come in
            if(!USBHandleBusy(USBMSDOutHandle))
            {
                USBMSDOutHandle = USBRxOnePacket(MSD_DATA_OUT_EP,(BYTE*)&msd_cbw,sizeof(msd_cbw));
            }
        
           	MSD_State=MSD_WAIT;
            break;
            
        default:
            //Illegal condition that should not happen, but might occur if the
            //device firmware incorrectly calls MSDTasks() prior to calling
            //USBMSDInit() during the set-configuration portion of enumeration.
            MSD_State=MSD_WAIT;
    }
    
    return MSD_State;
}