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(); }
/******************************************************************** * Function: UsbTasks() * * Precondition: * * Input: None. * * Output: None. * * Side Effects: None. * * Overview: This function transmits frames and received frames to and from USB. * * * Note: None. ********************************************************************/ void UsbTasks(void) { UINT TxLen; UINT8 *TxPtr; #if defined(USB_POLLING) //This function must be called everytime. This is a stack function. USBDeviceTasks(); #endif // Check if bootloader has something to send out to PC. TxLen = FRAMEWORK_GetTransmitFrame(UsbTxData); // Initialize the transmit pointer. TxPtr = &UsbTxData[0]; while(TxLen) { while(UsbTxBusy()); // Wait for USB transmit completion. // Send the packet (USB endpoint size is always 64 bytes) USBTxOnePacket(HID_EP, TxPtr, MaxUsbPacketSize); if(TxLen > MaxUsbPacketSize) { // Send pending bytes in next loop. TxLen -= MaxUsbPacketSize; // Point to next 64bytes. TxPtr += MaxUsbPacketSize; // Probably a wait is needed here, otherwise PC app may miss frames. //Wait(); } else { // No more bytes. TxLen = 0; } } // Following part of the code checks if there is any data from USB. // If there are any data available, it just pushes the data to the frame work. // Framework decodes the packet and takes necessary action like erasing/ programming etc. if(UsbRxDataAvlbl())// Check if we have got any data from USB. { // Yes, we got a packet from HID End point. // Pass the buffer to frame work. Framework decodes the packet and executes the Bootloder specific commands (Erasing/Programming etc). FRAMEWORK_BuildRxFrame(UsbRxData, MaxUsbPacketSize); // Re-arm the HID endpoint to receive next packet.(Remember! We have armed the HID endpoint for the first time in function USBCBInitEP()) USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)UsbRxData,MaxUsbPacketSize); } }
//------------------------------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(); }
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
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; }
/****************************************************************************** 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; } } }
/****************************************************************************** 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: 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; }
USB_HANDLE ChipKITUSBTxOnePacket(BYTE ep, BYTE* data, WORD len) { return(USBTxOnePacket(ep, data, len)); }
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); } }
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
void hidTxOnePacket(void) { hidTxHandle = USBTxOnePacket(HID_EP, (BYTE*)sndHidDataBuffer, 64); }
void midiTxOnePacket(BYTE *packet, BYTE len) { midiTxHandle = USBTxOnePacket(MIDI_EP, packet, len); }
/********************************************************************* * 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: 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; }