Пример #1
0
/**
 * Post-processes a command given the case identified during the
 * pre-processing step.
 * Depending on the case, one of the following actions can be done:
 *           - Bulk IN endpoint is stalled
 *           - Bulk OUT endpoint is stalled
 *           - CSW status set to phase error
 * \param  pMsdDriver Pointer to a MSDDriver instance
 * \return If the device is halted
 */
static unsigned char MSDD_PostProcessCommand(MSDDriver *pMsdDriver)
{
    MSDCommandState *commandState = &(pMsdDriver->commandState);
    MSCsw           *csw = &(commandState->csw);
    unsigned char haltStatus = 0;

    /* STALL Bulk IN endpoint ? */
    if ((commandState->postprocess & MSDD_CASE_STALL_IN) != 0) {

        TRACE_INFO_WP("StallIn ");
        //MSDD_Halt(MSDD_CASE_STALL_IN);
        USBD_Halt(commandState->pipeIN);
        haltStatus = 1;
    }

    /* STALL Bulk OUT endpoint ? */
    if ((commandState->postprocess & MSDD_CASE_STALL_OUT) != 0) {

        TRACE_INFO_WP("StallOut ");
        //MSDD_Halt(MSDD_CASE_STALL_OUT);
        USBD_Halt(commandState->pipeOUT);
        haltStatus = 1;
    }

    /* Set CSW status code to phase error ? */
    if ((commandState->postprocess & MSDD_CASE_PHASE_ERROR) != 0) {

        TRACE_INFO_WP("PhaseErr ");
        csw->bCSWStatus = MSD_CSW_PHASE_ERROR;
    }

    return haltStatus;
}
Пример #2
0
//-----------------------------------------------------------------------------
/// HALT Specified USB pipe.
/// \param stallCASE Case of the stall condition (Bulk In/Out/Both).
//-----------------------------------------------------------------------------
void MSDD_Halt(unsigned int stallCASE)
{
    if (stallCASE & MSDD_CASE_STALL_OUT) {

        USBD_Halt(MSDDriverDescriptors_BULKOUT);
    }

    if (stallCASE & MSDD_CASE_STALL_IN) {

        USBD_Halt(MSDDriverDescriptors_BULKIN);
    }
}
Пример #3
0
//------------------------------------------------------------------------------
/// Handles the given request if it is standard, otherwise STALLs it.
/// \param pDriver  Pointer to a USBDDriver instance.
/// \param pRequest  Pointer to a USBGenericRequest instance.
//------------------------------------------------------------------------------
void USBDDriver_RequestHandler(
    USBDDriver *pDriver,
    const USBGenericRequest *pRequest)
{
    unsigned char cfgnum;
    unsigned char infnum;
    unsigned char eptnum;
    unsigned char setting;
    unsigned char type;
    unsigned char indexDesc;
    unsigned int length;
    unsigned int address;

    TRACE_INFO_WP("Std ");

    // Check request code
    switch (USBGenericRequest_GetRequest(pRequest)) {

        case USBGenericRequest_GETDESCRIPTOR:
            TRACE_INFO_WP("gDesc ");

            // Send the requested descriptor
            type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
            indexDesc = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
            length = USBGenericRequest_GetLength(pRequest);
            GetDescriptor(pDriver, type, indexDesc, length);
            break;

        case USBGenericRequest_SETADDRESS:
            TRACE_INFO_WP("sAddr ");

            // Sends a zero-length packet and then set the device address
            address = USBSetAddressRequest_GetAddress(pRequest);
            USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
            break;

        case USBGenericRequest_SETCONFIGURATION:
            TRACE_INFO_WP("sCfg ");

            // Set the requested configuration
            cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
            SetConfiguration(pDriver, cfgnum);
            break;

        case USBGenericRequest_GETCONFIGURATION:
            TRACE_INFO_WP("gCfg ");

            // Send the current configuration number
            GetConfiguration(pDriver);
            break;

        case USBGenericRequest_GETSTATUS:
            TRACE_INFO_WP("gSta ");
    
            // Check who is the recipient
            switch (USBGenericRequest_GetRecipient(pRequest)) {
    
                case USBGenericRequest_DEVICE:
                    TRACE_INFO_WP("Dev ");
    
                    // Send the device status
                    GetDeviceStatus(pDriver);
                    break;
    
                case USBGenericRequest_ENDPOINT:
                    TRACE_INFO_WP("Ept ");
    
                    // Send the endpoint status
                    eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
                    GetEndpointStatus(eptnum);
                    break;
    
                default:
                    TRACE_WARNING(
                              "USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
                              USBGenericRequest_GetRecipient(pRequest));
                    USBD_Stall(0);
            }
            break;

        case USBGenericRequest_CLEARFEATURE:
            TRACE_INFO_WP("cFeat ");

            // Check which is the requested feature
            switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {

                case USBFeatureRequest_ENDPOINTHALT:
                    TRACE_INFO_WP("Hlt ");

                    // Unhalt endpoint and send a zero-length packet
                    USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
                    USBD_Write(0, 0, 0, 0, 0);
                    break;

                case USBFeatureRequest_DEVICEREMOTEWAKEUP:
                    TRACE_INFO_WP("RmWU ");

                    // Disable remote wake-up and send a zero-length packet
                    pDriver->isRemoteWakeUpEnabled = 0;
                    USBD_Write(0, 0, 0, 0, 0);
                    break;

                default:
                    TRACE_WARNING(
                              "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
                              USBFeatureRequest_GetFeatureSelector(pRequest));
                    USBD_Stall(0);
            }
            break;

    case USBGenericRequest_SETFEATURE:
        TRACE_INFO_WP("sFeat ");

        // Check which is the selected feature
        switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {

            case USBFeatureRequest_DEVICEREMOTEWAKEUP:
                TRACE_INFO_WP("RmWU ");

                // Enable remote wake-up and send a ZLP
                pDriver->isRemoteWakeUpEnabled = 1;
                USBD_Write(0, 0, 0, 0, 0);
                break;

            case USBFeatureRequest_ENDPOINTHALT:
                TRACE_INFO_WP("Halt ");
                // Halt endpoint
                USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
                USBD_Write(0, 0, 0, 0, 0);
                break;

#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)

            case USBFeatureRequest_TESTMODE:
                // 7.1.20 Test Mode Support
                if ((USBGenericRequest_GetType(pRequest) == USBGenericRequest_DEVICE)
                    && ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) {

                    // Handle test request
                    USBDDriver_Test(USBFeatureRequest_GetTestSelector(pRequest));
                }
                else {

                    USBD_Stall(0);
                }
                break;
#endif
#if defined(CHIP_USB_OTGHS)
            case USBFeatureRequest_OTG_B_HNP_ENABLE:
                    TRACE_INFO_WP("OTG_B_HNP_ENABLE ");
                    otg_features_supported |= 1<<USBFeatureRequest_OTG_B_HNP_ENABLE;
                    USBD_Write(0, 0, 0, 0, 0);
                break;
            case USBFeatureRequest_OTG_A_HNP_SUPPORT:
                    TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
                    otg_features_supported |= 1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
                    USBD_Write(0, 0, 0, 0, 0);
                break;
            case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
                    TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
                    otg_features_supported |= 1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
                    USBD_Write(0, 0, 0, 0, 0);
                break;
#endif
            default:
                TRACE_WARNING(
                          "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
                          USBFeatureRequest_GetFeatureSelector(pRequest));
                USBD_Stall(0);
        }
        break;

    case USBGenericRequest_SETINTERFACE:
        TRACE_INFO_WP("sInterface ");

        infnum = USBInterfaceRequest_GetInterface(pRequest);
        setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
        SetInterface(pDriver, infnum, setting);
        break;

    case USBGenericRequest_GETINTERFACE:
        TRACE_INFO_WP("gInterface ");

        infnum = USBInterfaceRequest_GetInterface(pRequest);
        GetInterface(pDriver, infnum);
        break;

    default:
        TRACE_WARNING(
                  "USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
                  USBGenericRequest_GetRequest(pRequest));
        USBD_Stall(0);
    }
}
Пример #4
0
/**
 * Handles the given request if it is standard, otherwise STALLs it.
 * \param pDriver  Pointer to a USBDDriver instance.
 * \param pRequest  Pointer to a USBGenericRequest instance.
 */
void USBDDriver_RequestHandler(
    USBDDriver *pDriver,
    const USBGenericRequest *pRequest)
{
    uint8_t cfgnum;
    uint8_t infnum;
    uint8_t eptnum;
    uint8_t setting;
    uint8_t type;
    uint8_t indexDesc;
    uint32_t length;
    uint32_t address;

    TRACE_INFO_WP("Std ");

    /* Check request code */
    switch (USBGenericRequest_GetRequest(pRequest)) {

        case USBGenericRequest_GETDESCRIPTOR:
            TRACE_INFO_WP("gDesc ");

            /* Send the requested descriptor */
            type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
            indexDesc = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
            length = USBGenericRequest_GetLength(pRequest);
            GetDescriptor(pDriver, type, indexDesc, length);
            break;

        case USBGenericRequest_SETADDRESS:
            TRACE_INFO_WP("sAddr ");

            /* Sends a zero-length packet and then set the device address */
            address = USBSetAddressRequest_GetAddress(pRequest);
            USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
            break;

        case USBGenericRequest_SETCONFIGURATION:
            TRACE_INFO_WP("sCfg ");

            /* Set the requested configuration */
            cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
            SetConfiguration(pDriver, cfgnum);
            break;

        case USBGenericRequest_GETCONFIGURATION:
            TRACE_INFO_WP("gCfg ");

            /* Send the current configuration number */
            GetConfiguration(pDriver);
            break;

        case USBGenericRequest_GETSTATUS:
            TRACE_INFO_WP("gSta ");

            /* Check who is the recipient */
            switch (USBGenericRequest_GetRecipient(pRequest)) {

                case USBGenericRequest_DEVICE:
                    TRACE_INFO_WP("Dev ");

                    /* Send the device status */
                    GetDeviceStatus(pDriver);
                    break;

                case USBGenericRequest_ENDPOINT:
                    TRACE_INFO_WP("Ept ");

                    /* Send the endpoint status */
                    eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
                    GetEndpointStatus(eptnum);
                    break;

                default:
                    TRACE_WARNING(
                              "USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
                              USBGenericRequest_GetRecipient(pRequest));
                    USBD_Stall(0);
            }
            break;

        case USBGenericRequest_CLEARFEATURE:
            TRACE_INFO_WP("cFeat ");

            /* Check which is the requested feature */
            switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {

                case USBFeatureRequest_ENDPOINTHALT:
                    TRACE_INFO_WP("Hlt ");

                    /* Unhalt endpoint and send a zero-length packet */
                    USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
                    USBD_Write(0, 0, 0, 0, 0);
                    break;

                case USBFeatureRequest_DEVICEREMOTEWAKEUP:
                    TRACE_INFO_WP("RmWU ");

                    /* Disable remote wake-up and send a zero-length packet */
                    pDriver->isRemoteWakeUpEnabled = 0;
                    USBD_Write(0, 0, 0, 0, 0);
                    break;

                default:
                    TRACE_WARNING(
                              "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
                              USBFeatureRequest_GetFeatureSelector(pRequest));
                    USBD_Stall(0);
            }
            break;

    case USBGenericRequest_SETFEATURE:
        TRACE_INFO_WP("sFeat ");

        /* Check which is the selected feature */
        switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {

            case USBFeatureRequest_DEVICEREMOTEWAKEUP:
                TRACE_INFO_WP("RmWU ");

                /* Enable remote wake-up and send a ZLP */
                pDriver->isRemoteWakeUpEnabled = 1;
                USBD_Write(0, 0, 0, 0, 0);
                break;

            case USBFeatureRequest_ENDPOINTHALT:
                TRACE_INFO_WP("Halt ");
                /* Halt endpoint */
                USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
                USBD_Write(0, 0, 0, 0, 0);
                break;
            case USBFeatureRequest_OTG_B_HNP_ENABLE:
                    TRACE_INFO_WP("OTG_B_HNP_ENABLE ");
                    pDriver->otg_features_supported |=
                        1<<USBFeatureRequest_OTG_B_HNP_ENABLE;
                    USBD_Write(0, 0, 0, 0, 0);
                break;
            case USBFeatureRequest_OTG_A_HNP_SUPPORT:
                    TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
                    pDriver->otg_features_supported |=
                        1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
                    USBD_Write(0, 0, 0, 0, 0);
                break;
            case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
                    TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
                    pDriver->otg_features_supported |=
                        1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
                    USBD_Write(0, 0, 0, 0, 0);
                break;

            default:
                TRACE_WARNING(
                          "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
                          USBFeatureRequest_GetFeatureSelector(pRequest));
                USBD_Stall(0);
        }
        break;

    case USBGenericRequest_SETINTERFACE:
        TRACE_INFO_WP("sInterface ");

        infnum = USBInterfaceRequest_GetInterface(pRequest);
        setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
        SetInterface(pDriver, infnum, setting);
        break;

    case USBGenericRequest_GETINTERFACE:
        TRACE_INFO_WP("gInterface ");

        infnum = USBInterfaceRequest_GetInterface(pRequest);
        GetInterface(pDriver, infnum);
        break;

    default:
        TRACE_WARNING(
                  "USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
                  USBGenericRequest_GetRequest(pRequest));
        USBD_Stall(0);
    }
}
Пример #5
0
/**
 * State machine for the MSD %device driver
 * \param  pMsdDriver Pointer to a MSDDriver instance
 */
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;
    #if 1
        status = USBD_Read(commandState->pipeOUT,
                           cbw,
                           MSD_CBW_SIZE,
                           (TransferCallback) MSDDriver_Callback,
                           (void *) transfer);
    #else
        status = MSDD_Read(cbw,
                           MSD_CBW_SIZE,
                           (TransferCallback) MSDDriver_Callback,
                           (void *) transfer);
    #endif

        /* 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------------------------------\n\r");

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

                TRACE_INFO("MSDD_StateMachine: EP 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 (len %d)\n\r",
                    (int)transfer->transferred);

                /* 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);
                USBD_Halt(commandState->pipeIN);
                USBD_Halt(commandState->pipeOUT);

                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);
                USBD_Halt(commandState->pipeIN);
                USBD_Halt(commandState->pipeOUT);

                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 */
                if (MSDD_PostProcessCommand(pMsdDriver)) {

                    TRACE_INFO_WP("WaitHALT ");
                    pMsdDriver->state = MSDD_STATE_WAIT_HALT;
                }
                else {

                    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 */
      #if 1
        status = USBD_Write(commandState->pipeIN,
                            csw,
                            MSD_CSW_SIZE,
                            (TransferCallback) MSDDriver_Callback,
                            (void *) transfer);
      #else
        status = MSDD_Write(csw,
                            MSD_CSW_SIZE,
                            (TransferCallback) MSDDriver_Callback,
                            (void *) transfer);
      #endif

        /* 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: EP 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;

    /*---------------------- */
    case MSDD_STATE_WAIT_HALT:
    /*---------------------- */
        //if (MSDD_IsHalted() == 0) {
        if (!USBD_IsHalted(commandState->pipeIN)) {

            pMsdDriver->state = MSDD_STATE_SEND_CSW;
        }
        break;
    }
}