uint8_t USBMSC_pollCommand () { uint16_t state; uint8_t edbIndex; uint8_t * pCT1; uint8_t * pCT2; edbIndex = stUsbHandle[MSC0_INTFNUM].edb_Index; pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX; pCT2 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY; //check if currently transmitting data.. if (MscReadControl.bReadProcessing == TRUE){ state = usbDisableOutEndpointInterrupt(edbIndex); //atomic operation - disable interrupts if ((MscReadControl.dwBytesToSendLeft == 0) && (MscReadControl.lbaCount == 0)){ //data is no more processing - clear flags.. MscReadControl.bReadProcessing = FALSE; usbRestoreOutEndpointInterrupt(state); } else { if (!(tInputEndPointDescriptorBlock[edbIndex].bEPCNF & EPCNF_STALL)){ //if it is not stalled - contiune communication USBIEPIFG |= 1 << (edbIndex + 1); //trigger IN interrupt to finish data tranmition } usbRestoreOutEndpointInterrupt(state); return (USBMSC_PROCESS_BUFFER); } } if (MscState.isMSCConfigured == FALSE){ return (USBMSC_OK_TO_SLEEP); } if (!MscState.bMscSendCsw){ if (MscState.bMscCbwReceived){ if (Scsi_Verify_CBW() == SUCCESS){ //Successful reception of CBW //Parse the CBW opcode and invoke the right command handler function Scsi_Cmd_Parser(MSC0_INTFNUM); MscState.bMscSendCsw = TRUE; } MscState.bMscCbwReceived = FALSE; //CBW is performed! } else { return (USBMSC_OK_TO_SLEEP); } //check if any of out pipes has pending data and trigger interrupt if ((MscWriteControl.pCT1 != NULL) && ((*MscWriteControl.pCT1 & EPBCNT_NAK ) || (*MscWriteControl.pCT2 & EPBCNT_NAK ))){ USBOEPIFG |= 1 << (edbIndex + 1); //trigger OUT interrupt again return (USBMSC_PROCESS_BUFFER); //do not asleep, as data is coming in //and follow up data perform will be required. } } if (MscState.bMscSendCsw){ if (MscState.bMcsCommandSupported == TRUE){ //watiting till transport is finished! if ((MscWriteControl.bWriteProcessing == FALSE) && (MscReadControl.bReadProcessing == FALSE) && (MscReadControl.lbaCount == 0)){ //Send CSW if (MscState.stallAtEndofTx == TRUE) { if ((*pCT1 & EPBCNT_NAK) && (*pCT2 & EPBCNT_NAK)) { MscState.stallAtEndofTx = FALSE; usbStallInEndpoint(MSC0_INTFNUM); } } else if (SUCCESS == Scsi_Send_CSW(MSC0_INTFNUM)){ MscState.bMscSendCsw = FALSE; return (USBMSC_OK_TO_SLEEP); } } else { MSCFromHostToBuffer(); } } } return (USBMSC_PROCESS_BUFFER); //When MscState.bMcsCommandSupported = FALSE, bReadProcessing became true, and //bWriteProcessing = true. }
/*This is the core function called by application to handle the MSC SCSI state * machine */ BYTE USBMSC_poll () { BYTE edbIndex; edbIndex = stUsbHandle[MSC0_INTFNUM].edb_Index; //check if currently transmitting data.. if (MscReadControl.bReadProcessing == TRUE){ BYTE bGIE; bGIE = (__get_SR_register() & GIE); //save interrupt status //atomic operation - disable interrupts _DINT_FET(); //Disable global interrupts if ((MscReadControl.dwBytesToSendLeft == 0) && (MscReadControl.lbaCount == 0)){ //data is no more processing - clear flags.. MscReadControl.bReadProcessing = FALSE; __bis_SR_register(bGIE); //restore interrupt status } else { if (!(tInputEndPointDescriptorBlock[edbIndex].bEPCNF & EPCNF_STALL)){ //if it is not stalled - contiune communication USBIEPIFG |= 1 << (edbIndex + 1); //trigger IN interrupt to finish data tranmition } __bis_SR_register(bGIE); //restore interrupt status return (kUSBMSC_processBuffer); } } if (MscState.isMSCConfigured == FALSE){ return (kUSBMSC_okToSleep); } if (!MscState.bMscSendCsw){ if (MscState.bMscCbwReceived){ if (Scsi_Verify_CBW() == SUCCESS){ //Successful reception of CBW //Parse the CBW opcode and invoke the right command handler function Scsi_Cmd_Parser(MSC0_INTFNUM); MscState.bMscSendCsw = TRUE; } MscState.bMscCbwReceived = FALSE; //CBW is performed! } else { return (kUSBMSC_okToSleep); } //check if any of out pipes has pending data and trigger interrupt if ((MscWriteControl.pCT1 != NULL) && ((*MscWriteControl.pCT1 & EPBCNT_NAK ) || (*MscWriteControl.pCT2 & EPBCNT_NAK ))){ USBOEPIFG |= 1 << (edbIndex + 1); //trigger OUT interrupt again return (kUSBMSC_okToSleep); //do not asleep, as data is coming in //and follow up data perform will be required. } } if (MscState.bMscSendCsw){ if (MscState.bMcsCommandSupported == TRUE){ //watiting till transport is finished! if ((MscWriteControl.bWriteProcessing == FALSE) && (MscReadControl.bReadProcessing == FALSE) && (MscReadControl.lbaCount == 0)){ //Send CSW if (SUCCESS == Scsi_Send_CSW(MSC0_INTFNUM)){ MscState.bMscSendCsw = FALSE; return (kUSBMSC_okToSleep); } } else { MSCFromHostToBuffer(); } } } return (kUSBMSC_processBuffer); //When MscState.bMcsCommandSupported = FALSE, bReadProcessing became true, and //bWriteProcessing = true. }
__interrupt VOID iUsbInterruptHandler(VOID) { BYTE bWakeUp = FALSE; //Check if the setup interrupt is pending. //We need to check it before other interrupts, //to work around that the Setup Int has lower priority then Input Endpoint 0 if (USBIFG & SETUPIFG) { bWakeUp = SetupPacketInterruptHandler(); USBIFG &= ~SETUPIFG; // clear the interrupt bit } switch (__even_in_range(USBVECINT & 0x3f, USBVECINT_OUTPUT_ENDPOINT7)) { case USBVECINT_NONE: break; case USBVECINT_PWR_DROP: __no_operation(); break; case USBVECINT_PLL_LOCK: break; case USBVECINT_PLL_SIGNAL: break; case USBVECINT_PLL_RANGE: if (wUsbEventMask & kUSB_clockFaultEvent) { bWakeUp = USB_handleClockEvent(); } break; case USBVECINT_PWR_VBUSOn: PWRVBUSonHandler(); if (wUsbEventMask & kUSB_VbusOnEvent) { bWakeUp = USB_handleVbusOnEvent(); } break; case USBVECINT_PWR_VBUSOff: PWRVBUSoffHandler(); if (wUsbEventMask & kUSB_VbusOffEvent) { bWakeUp = USB_handleVbusOffEvent(); } break; case USBVECINT_USB_TIMESTAMP: break; case USBVECINT_INPUT_ENDPOINT0: IEP0InterruptHandler(); break; case USBVECINT_OUTPUT_ENDPOINT0: OEP0InterruptHandler(); break; case USBVECINT_RSTR: USB_reset(); if (wUsbEventMask & kUSB_UsbResetEvent) { bWakeUp = USB_handleResetEvent(); } break; case USBVECINT_SUSR: USB_suspend(); if (wUsbEventMask & kUSB_UsbSuspendEvent) { bWakeUp = USB_handleSuspendEvent(); } break; case USBVECINT_RESR: USB_resume(); if (wUsbEventMask & kUSB_UsbResumeEvent) { bWakeUp = USB_handleResumeEvent(); } //-- after resume we will wake up! Independ what event handler says. bWakeUp = TRUE; break; case USBVECINT_SETUP_PACKET_RECEIVED: // NAK both IEP and OEP enpoints tEndPoint0DescriptorBlock.bIEPBCNT = EPBCNT_NAK; tEndPoint0DescriptorBlock.bOEPBCNT = EPBCNT_NAK; SetupPacketInterruptHandler(); break; case USBVECINT_STPOW_PACKET_RECEIVED: break; case USBVECINT_INPUT_ENDPOINT1: bWakeUp = MSCToHostFromBuffer(); break; case USBVECINT_INPUT_ENDPOINT2: break; case USBVECINT_INPUT_ENDPOINT3: //send saved bytes from buffer... bWakeUp = CdcToHostFromBuffer(CDC0_INTFNUM); break; case USBVECINT_INPUT_ENDPOINT4: //send saved bytes from buffer... bWakeUp = HidToHostFromBuffer(HID0_INTFNUM); break; case USBVECINT_INPUT_ENDPOINT5: break; case USBVECINT_INPUT_ENDPOINT6: break; case USBVECINT_INPUT_ENDPOINT7: break; case USBVECINT_OUTPUT_ENDPOINT1: bWakeUp = MSCFromHostToBuffer(); break; case USBVECINT_OUTPUT_ENDPOINT2: break; case USBVECINT_OUTPUT_ENDPOINT3: //call callback function if no receive operation is underway if (!CdcIsReceiveInProgress(CDC0_INTFNUM)) { if (wUsbEventMask & kUSB_dataReceivedEvent) { bWakeUp = USBCDC_handleDataReceived(CDC0_INTFNUM); } } else { //complete receive opereation - copy data to user buffer bWakeUp = CdcToBufferFromHost(CDC0_INTFNUM); } break; case USBVECINT_OUTPUT_ENDPOINT4: //call callback function if no receive operation is underway if (!HidIsReceiveInProgress(HID0_INTFNUM)) { if (wUsbEventMask & kUSB_dataReceivedEvent) { bWakeUp = USBHID_handleDataReceived(HID0_INTFNUM); } } else { //complete receive opereation - copy data to user buffer bWakeUp = HidToBufferFromHost(HID0_INTFNUM); } break; case USBVECINT_OUTPUT_ENDPOINT5: break; case USBVECINT_OUTPUT_ENDPOINT6: break; case USBVECINT_OUTPUT_ENDPOINT7: break; default: break; } if (bWakeUp) { __bic_SR_register_on_exit(LPM3_bits); // Exit LPM0-3 __no_operation(); // Required for debugger } }