/********************************************************************************* 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; }
/********************************************************************************* 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; }