MSDD_StateMachine
Default mainpageat91libusbdevicemassstorageMSDD_StateMachine
Description Source Call Graph
Start Line: 402
void MSDD_StateMachine(MSDDriver *pMsdDriver)
{
    MSDCommandState *commandState = &(pMsdDriver->commandState);
    MSCbw           *cbw = &(commandState->cbw);
    MSCsw           *csw = &(commandState->csw);
    MSDTransfer     *transfer = &(commandState->transfer);
    unsigned char   status;

    // Identify current driver state
    switch (pMsdDriver->state) {
    //----------------------
    case MSDD_STATE_READ_CBW:
    //----------------------
        // Start the CBW read operation
        transfer->semaphore = 0;
        status = MSDD_Read(cbw,
                           MSD_CBW_SIZE,
                           (TransferCallback) MSDDriver_Callback,
                           (void *) transfer);

        // Check operation result code
        if (status == USBD_STATUS_SUCCESS) {

            // If the command was successful, wait for transfer
            pMsdDriver->state = MSDD_STATE_WAIT_CBW;
        }
        break;

    //----------------------
    case MSDD_STATE_WAIT_CBW:
    //----------------------
        // Check transfer semaphore
        if (transfer->semaphore > 0) {

            // Take semaphore and terminate transfer
            transfer->semaphore--;

            // Check if transfer was successful
            if (transfer->status == USBD_STATUS_SUCCESS) {

                TRACE_INFO_WP("------------------------------\n\r");

                // Process received command
                pMsdDriver->state = MSDD_STATE_PROCESS_CBW;
            }
            else if (transfer->status == USBD_STATUS_RESET) {

                TRACE_INFO("MSDD_StateMachine: Endpoint resetted\n\r");
                pMsdDriver->state = MSDD_STATE_READ_CBW;
            }
            else {

                TRACE_WARNING(
                    "MSDD_StateMachine: Failed to read CBW\n\r");
                pMsdDriver->state = MSDD_STATE_READ_CBW;
            }
        }
        break;

    //-------------------------
    case MSDD_STATE_PROCESS_CBW:
    //-------------------------
        // Check if this is a new command
        if (commandState->state == 0) {

            // Copy the CBW tag
            csw->dCSWTag = cbw->dCBWTag;

            // Check that the CBW is 31 bytes long
            if ((transfer->transferred != MSD_CBW_SIZE) ||
                (transfer->remaining != 0)) {

                TRACE_WARNING(
                    "MSDD_StateMachine: Invalid CBW (Bad Length)\n\r");

                // Wait for a reset recovery
                pMsdDriver->waitResetRecovery = 1;

                // Halt the Bulk-IN and Bulk-OUT pipes
                MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN);

                csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
                pMsdDriver->state = MSDD_STATE_READ_CBW;

            }
            // Check the CBW Signature
            else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) {

                TRACE_WARNING(
                    "MSD_BOTStateMachine: Invalid CBW (Bad signature)\n\r");

                // Wait for a reset recovery
                pMsdDriver->waitResetRecovery = 1;

                // Halt the Bulk-IN and Bulk-OUT pipes
                MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN);

                csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
                pMsdDriver->state = MSDD_STATE_READ_CBW;
            }
            else {

                // Pre-process command
                MSDD_PreProcessCommand(pMsdDriver);
            }
        }

        // Process command
        if (csw->bCSWStatus == MSDD_STATUS_SUCCESS) {

            if (MSDD_ProcessCommand(pMsdDriver)) {

                // Post-process command if it is finished
                MSDD_PostProcessCommand(pMsdDriver);
                pMsdDriver->state = MSDD_STATE_SEND_CSW;
            }
            TRACE_INFO_WP("\n\r");
        }

        break;

    //----------------------
    case MSDD_STATE_SEND_CSW:
    //----------------------
        // Set signature
        csw->dCSWSignature = MSD_CSW_SIGNATURE;

        // Start the CSW write operation
        status = MSDD_Write(csw,
                            MSD_CSW_SIZE,
                            (TransferCallback) MSDDriver_Callback,
                            (void *) transfer);

        // Check operation result code
        if (status == USBD_STATUS_SUCCESS) {

            TRACE_INFO_WP("SendCSW ");

            // Wait for end of transfer
            pMsdDriver->state = MSDD_STATE_WAIT_CSW;
        }
        break;

    //----------------------
    case MSDD_STATE_WAIT_CSW:
    //----------------------
        // Check transfer semaphore
        if (transfer->semaphore > 0) {

            // Take semaphore and terminate transfer
            transfer->semaphore--;

            // Check if transfer was successful
            if (transfer->status == USBD_STATUS_RESET) {

                TRACE_INFO("MSDD_StateMachine: Endpoint resetted\n\r");
            }
            else if (transfer->status == USBD_STATUS_ABORTED) {

                TRACE_WARNING(
                    "MSDD_StateMachine: Failed to send CSW\n\r");
            }
            else {

                TRACE_INFO_WP("ok");
            }

            // Read new CBW
            pMsdDriver->state = MSDD_STATE_READ_CBW;
        }
        break;
    }
}