⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bot.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 3 页
字号:

    FUNCTION_LEAVE_MSG();
}


// Process a USB Clear Feature Standard Request. The MDD has already 
// responded to the request so this is strictly informational.
static
VOID
BOT_HandleClearFeature(
    USB_DEVICE_REQUEST udr
    )
{
    SETFNAME(_T("BOT_HandleClearFeature"));
    FUNCTION_ENTER_MSG();
    
    if ( (udr.bmRequestType & USB_REQUEST_FOR_ENDPOINT) && 
         (udr.wValue == USB_FEATURE_ENDPOINT_STALL) ) {
        UFN_PIPE hPipe = BOT_GetPipe(udr.wIndex);

        if (hPipe != NULL) {
            if ( (hPipe == g_hBIPipe) && (g_MscState == MSC_STATE_WAIT_FOR_RESET) ) {
                ChangeMscState(MSC_STATE_STATUS_TRANSPORT);
                BOT_BuildCSW(g_pCbw->dCBWTag, g_dwCSWDataResidue, (BYTE) g_dwCSWStatus);
                BOT_SetupTx(&g_rgPipeTransfers[IN_TRANSFER], g_rgbCXWBuffer, sizeof(CSW));  
            }
        }
    }
}


// Process a USB Class Request.  Call Request-specific handler.
static
CONTROL_RESPONSE
BOT_HandleClassRequest(
    USB_DEVICE_REQUEST udr
    )
{
    SETFNAME(_T("BOT_HandleClassRequest"));
    FUNCTION_ENTER_MSG();

    CONTROL_RESPONSE response = CR_STALL_DEFAULT_PIPE;
           
    if (udr.bmRequestType == 
         (USB_REQUEST_CLASS | USB_REQUEST_FOR_INTERFACE | USB_REQUEST_HOST_TO_DEVICE) ) {
        if (udr.bRequest == BOT_RESET_REQUEST) {
            if ( (udr.wValue == 0) && (udr.wIndex == 0) && (udr.wLength == 0) ) {
                // Bulk-only mass storage reset
                DEBUGMSG(ZONE_COMMENT,
                    (_T("%s Bulk-only mass storage reset class request\r\n"),
                    pszFname));
                BOT_ResetPipeState(&g_psDefaultPipeState);
                BOT_ResetPipeState(&g_psBIPipeState);
                BOT_ResetPipeState(&g_psBOPipeState);
                response = CR_SUCCESS_SEND_CONTROL_HANDSHAKE;
            }
            else {
                ERRORMSG(1, (_T("%s Malformed bulk-only mass storage reset ")
                     _T("{value=0x%x, index=0x%x, length=0x%x}\r\n"), 
                    pszFname, udr.wValue, udr.wIndex, udr.wLength));
            }
        }
        else {
            ERRORMSG(1, (_T("%s Unrecognized BOT class bRequest -> 0x%x\r\n"), 
                pszFname, udr.bmRequestType));
        }
    }
    else if (udr.bmRequestType == 
       (USB_REQUEST_CLASS | USB_REQUEST_FOR_INTERFACE | USB_REQUEST_DEVICE_TO_HOST) ) {
        if (udr.bRequest == BOT_GET_MAX_LUN_REQUEST) {
            if ( (udr.wValue == 0) && (udr.wIndex == 0) && (udr.wLength == 1) ) {
                // Limited to a single LUN
                DEBUGMSG(ZONE_COMMENT, (_T("%s Get max LUN class request\r\n"),
                    pszFname));
                g_bScratch = 0;
                BOT_SetupTx(&g_rgPipeTransfers[CONTROL_TRANSFER], &g_bScratch, sizeof(g_bScratch));
                response = CR_SUCCESS;
            }
            else {
                ERRORMSG(1, (_T("%s Malformed get max LUN -> ")
                    _T("{value=0x%, index=0x%x, length=0x%x}\r\n"), 
                    pszFname, udr.wValue, udr.wIndex, udr.wLength));
            }
        }
        else {
            ERRORMSG(1, (_T("%s Unrecognized BOT class bRequest -> 0x%x\r\n"), 
                pszFname, udr.bmRequestType));
        }     
    }
    else {
        ERRORMSG(1, (_T("%s Unrecognized BOT class bRequest -> 0x%x\r\n"), 
            pszFname, udr.bmRequestType));
    }

    FUNCTION_LEAVE_MSG();

    return response;
}


// Process a USB Standard Request.  Call Request-specific handler.
static
VOID
BOT_HandleRequest(
    DWORD dwMsg,
    USB_DEVICE_REQUEST udr
    )
{
    SETFNAME(_T("BOT_HandleRequest"));
    FUNCTION_ENTER_MSG();

    CONTROL_RESPONSE response;

    if (dwMsg == UFN_MSG_PREPROCESSED_SETUP_PACKET) {
        response = CR_SUCCESS; // Don't respond since it was already handled.
        
        if ( udr.bmRequestType ==
            (USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_ENDPOINT) ) {
            switch (udr.bRequest) {
                case USB_REQUEST_CLEAR_FEATURE:
                    BOT_HandleClearFeature(udr);
                    break;
                default:
                    break;
            }
        }

        else if (udr.bmRequestType ==
            (USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_DEVICE) ) {
            if (udr.bRequest == USB_REQUEST_SET_CONFIGURATION) {                
                // Prepare for command transfer
//                ReceiveCBW();
            }
        }
    }
    else {
        DEBUGCHK(dwMsg == UFN_MSG_SETUP_PACKET);
        response = CR_STALL_DEFAULT_PIPE;

        if (udr.bmRequestType & USB_REQUEST_CLASS) {
            DEBUGMSG(ZONE_COMMENT, (_T("%s Class request\r\n"), pszFname));
//            ChangeMscState(MSC_STATE_IDLE);
            response = BOT_HandleClassRequest(udr);
        }
    }

    if (response == CR_STALL_DEFAULT_PIPE) {
        g_pUfnFuncs->lpStallPipe(g_hDevice, g_hDefaultPipe);
        g_pUfnFuncs->lpSendControlStatusHandshake(g_hDevice);
    }
    else if (response == CR_SUCCESS_SEND_CONTROL_HANDSHAKE) {
        g_pUfnFuncs->lpSendControlStatusHandshake(g_hDevice);
    }

    FUNCTION_LEAVE_MSG();
}


// Execute a Command-Block.
static
DWORD
BOT_ExecuteCB(
    PTRANSPORT_COMMAND  pCommand,
    PTRANSPORT_DATA     pData
    )
{
    SETFNAME(_T("BOT_ExecuteCB"));
    FUNCTION_ENTER_MSG();
    
    // Execute the command   
    DWORD dwResult = STORE_ExecuteCommand(pCommand, pData);
    if (dwResult == EXECUTE_PASS) {
        DEBUGMSG(ZONE_COMMENT, (_T("%s Command : passed\r\n"), pszFname));
    }
    else {
        DEBUGMSG(ZONE_ERROR, (_T("%s Command : failed\r\n"), pszFname));
    }
    
    FUNCTION_LEAVE_MSG();

    return dwResult;
}


// Process an Command-Block-Wrapper (CBW).
static
BOOL
BOT_HandleCBW(
    )
{
    SETFNAME(_T("BOT_HandleCBW"));
    FUNCTION_ENTER_MSG();
    
    BOOL    fData;
    DWORD   dwDirection;
    DWORD   dwDataSize;
    BOOL    fResult = FALSE;

    switch (g_MscState) {
        case MSC_STATE_COMMAND_TRANSPORT: {
            // Validate CBW
            if (g_pCbw->dCBWSignature != CBW_SIGNATURE) {
                ERRORMSG(1, (_T("%s Invalid CBW signature\r\n"), pszFname));
                // Reset state and stall the request
                ChangeMscState(MSC_STATE_WAIT_FOR_RESET);
                g_pUfnFuncs->lpStallPipe(g_hDevice, g_hBIPipe);
                g_pUfnFuncs->lpStallPipe(g_hDevice, g_hBOPipe);
                goto EXIT;
            }            

            // Read bCBWCBLength and CBWCB
            g_tcCommand.Length = g_pCbw->bCBWCBLength;
            g_tcCommand.CommandBlock = g_pCbw->CBWCB;

            DEBUGMSG(ZONE_COMMENT, (_T("%s Length: 0x%04x Flags: 0x%x CBWLen: 0x%x\r\n"),
                pszFname, g_pCbw->dCBWDataTransferLength, g_pCbw->bmCBWFlags, g_pCbw->bCBWCBLength));
            
            if (STORE_IsCommandSupported(&g_tcCommand, &fData, &dwDirection, 
                    &dwDataSize)) {
                g_dwCBWDataTransferLength = g_pCbw->dCBWDataTransferLength;

                g_tcCommand.Flags = dwDirection;
                g_tdData.RequestLength = g_dwCBWDataTransferLength;
                g_tdData.DataBlock = g_pbDataBuffer;

                // Do we need to create a larger data buffer?
                if (g_tdData.RequestLength > g_cbDataBuffer) {
                    g_pbDataBuffer = (PBYTE) LocalReAlloc(g_pbDataBuffer, 
                        g_tdData.RequestLength, LMEM_MOVEABLE);
                    if (g_pbDataBuffer == NULL) {
                        // We are in trouble. We cannot handle this request.
                        ERRORMSG(1, (_T("%s OUT OF MEMORY! STALLING REQUEST.\r\n"),
                            pszFname));

                        // Reset the pointer
                        g_pbDataBuffer = (PBYTE) g_tdData.DataBlock;
                        
                        // Reset state and stall the request
                        ChangeMscState(MSC_STATE_WAIT_FOR_RESET);
                        g_pUfnFuncs->lpStallPipe(g_hDevice, g_hBIPipe);
                        g_pUfnFuncs->lpStallPipe(g_hDevice, g_hBOPipe);
                        goto EXIT;
                    }
                    else {
                        g_tdData.DataBlock = g_pbDataBuffer;
                        g_cbDataBuffer = g_tdData.RequestLength;
                    }
                }

                if (fData) {
                    // Data command
                    if (dwDirection == DATA_IN) {                        
                        ChangeMscState(MSC_STATE_DATA_IN_TRANSPORT);
                        // Execute the command
                        g_dwCSWStatus = BOT_ExecuteCB(&g_tcCommand, &g_tdData);
                        if (g_dwCSWStatus == EXECUTE_PASS) {                            
                            DEBUGMSG(ZONE_COMMENT, (_T("%s request length = %u\r\n"), 
                                pszFname, g_tdData.RequestLength));
                            BOT_SetupTx(&g_rgPipeTransfers[IN_TRANSFER], (PBYTE) g_tdData.DataBlock,
                                g_tdData.TransferLength);                            
                            g_dwCSWDataResidue = g_dwCBWDataTransferLength - g_tdData.TransferLength;
                            DEBUGCHK(g_dwCSWDataResidue >= 0);
                            if (g_dwCSWDataResidue > 0) g_psBIPipeState.fSendingLess = TRUE;                            
                            fResult = TRUE;
                        }
                        else {                            
                            //
                            // the command failed--stall the request; after clearing the stall,
                            // the host will request a CSW
                            //                            
                            g_pUfnFuncs->lpStallPipe(g_hDevice, g_hBIPipe);
                            ChangeMscState(MSC_STATE_STATUS_TRANSPORT);
                            // prepare for CSW transfer
                            BOT_BuildCSW(g_pCbw->dCBWTag, 0, (BYTE) g_dwCSWStatus);
                            BOT_SetupTx(&g_rgPipeTransfers[IN_TRANSFER], g_rgbCXWBuffer, sizeof(CSW));
                        }
                    }
                    else if (dwDirection == DATA_OUT) {
                        ChangeMscState(MSC_STATE_DATA_OUT_TRANSPORT);
                        DEBUGMSG(ZONE_COMMENT, (_T("%s request length = %u\r\n"),
                            pszFname, g_tdData.RequestLength));   
                        BOT_SetupRx(&g_rgPipeTransfers[OUT_TRANSFER], (PBYTE) g_tdData.DataBlock, 
                            g_tdData.RequestLength);
                        fResult = TRUE;
                    }
                    else {
                        // This is impossible
                        DEBUGCHK(FALSE);
                    }
                }
                else {
                    // Non-data command. Execute the command and prepare for CSW transfer.
                    ChangeMscState(MSC_STATE_STATUS_TRANSPORT);
                    BOT_BuildCSW(g_pCbw->dCBWTag, 0, (BYTE) BOT_ExecuteCB(&g_tcCommand, NULL));
                    BOT_SetupTx(&g_rgPipeTransfers[IN_TRANSFER], g_rgbCXWBuffer, sizeof(CSW));                    
                    fResult = TRUE;
                }
            }
            else {
                // If the command is not supported, then return a phase error
                DEBUGMSG(ZONE_WARNING, (_T("%s command not supported\r\n"),
                    pszFname));

                // Prepare for CSW transfer
                ChangeMscState(MSC_STATE_WAIT_FOR_RESET);
                g_dwCSWDataResidue = 0;
                g_dwCSWStatus = EXECUTE_FAIL;

                g_pUfnFuncs->lpStallPipe(g_hDevice, g_hBIPipe);
            }
            
            break;
        }
        
        case MSC_STATE_DATA_IN_TRANSPORT:
            ChangeMscState(MSC_STATE_STATUS_TRANSPORT);
            BOT_BuildCSW(g_pCbw->dCBWTag, g_dwCSWDataResidue, (BYTE) g_dwCSWStatus);
            BOT_SetupTx(&g_rgPipeTransfers[IN_TRANSFER], g_rgbCXWBuffer, sizeof(CSW));
            fResult = TRUE;
            break;
            
        case MSC_STATE_DATA_OUT_TRANSPORT:
            // The data block has been transferred and is in g_tdData                       
            g_dwCSWStatus = BOT_ExecuteCB(&g_tcCommand, &g_tdData);
            g_dwCSWDataResidue = g_dwCBWDataTransferLength - g_tdData.TransferLength;            
            DEBUGCHK(g_dwCSWDataResidue >= 0);
            if (g_dwCSWDataResidue > 0) g_psBOPipeState.fSendingLess = TRUE;            
            ChangeMscState(MSC_STATE_STATUS_TRANSPORT);
            BOT_BuildCSW(g_pCbw->dCBWTag, g_dwCSWDataResidue, (UCHAR) g_dwCSWStatus);
            BOT_SetupTx(&g_rgPipeTransfers[IN_TRANSFER], g_rgbCXWBuffer, sizeof(CSW));
            fResult = TRUE;
            break;
        
        case MSC_STATE_STATUS_TRANSPORT:
            ChangeMscState(MSC_STATE_IDLE);
            // Prepare for command transfer
            ReceiveCBW();
            fResult = TRUE;
            break;

        case MSC_STATE_WAIT_FOR_RESET:
            fResult = TRUE;
            break;
        
        default:            
            // This is impossible
            DEBUGCHK(FALSE);
    }

EXIT:

    FUNCTION_LEAVE_MSG();

    return fResult;
}


static
VOID
ProcessBOPipeTransfer(
    DWORD cbTransferred
    )
{
    SETFNAME(_T("ProcessBOPipeTransfer"));
    FUNCTION_ENTER_MSG();

    if (g_MscState == MSC_STATE_COMMAND_TRANSPORT) {
        // Command state
        DEBUGCHK(cbTransferred == sizeof(CBW));
        DEBUGMSG(ZONE_COMMENT, (_T("%s Received CBW\r\n"),
            pszFname));
        BOT_HandleCBW();
        g_fCBWArrived = TRUE;
    }
    else if (g_MscState == MSC_STATE_DATA_OUT_TRANSPORT) {
        // Data out state
        DEBUGMSG(ZONE_COMMENT, (_T("%s Received data block\r\n"),
            pszFname));
        BOT_HandleCBW();
    }

    FUNCTION_LEAVE_MSG();
}


static
VOID
ProcessBIPipeTransfer(
    )
{
    SETFNAME(_T("ProcessBIPipeTransfer"));
    FUNCTION_ENTER_MSG();

    if (g_MscState == MSC_STATE_STATUS_TRANSPORT) {
        BOT_HandleCBW();
    }
    else if (g_MscState == MSC_STATE_DATA_IN_TRANSPORT) {
        if (g_psBIPipeState.fSendingLess) {
            g_psBIPipeState.fSendingLess = FALSE;
            g_pUfnFuncs->lpStallPipe(g_hDevice, g_hBIPipe);
            ChangeMscState(MSC_STATE_WAIT_FOR_RESET);
        }
        
        BOT_HandleCBW();
    }
    
    FUNCTION_LEAVE_MSG();
}


// Open the pipes associated with the default interface.
static
BOOL
BOT_OpenInterface(
    )
{
    SETFNAME(_T("BOT_OpenInterface"));
    FUNCTION_ENTER_MSG();
    
    BOOL fResult = FALSE;
    PUFN_ENDPOINT pEndpoint= GetEndpointDescriptor(g_SpeedSupported);

    // Open the pipes of the associated interface.

    DEBUGCHK(g_hBOPipe == NULL);
    DEBUGCHK(g_hBIPipe == NULL);
    
    DWORD dwRet = g_pUfnFuncs->lpOpenPipe(g_hDevice, 
        pEndpoint[0].Descriptor.bEndpointAddress,
        &g_hBIPipe);
    if (dwRet != ERROR_SUCCESS) {
        ERRORMSG(1, (_T("%s Failed to open bulk in pipe\r\n"),
            pszFname));
        goto EXIT;
    }

    dwRet = g_pUfnFuncs->lpOpenPipe(g_hDevice, 
        pEndpoint[1].Descriptor.bEndpointAddress,
        &g_hBOPipe);
    if (dwRet != ERROR_SUCCESS) {
        ERRORMSG(1, (_T("%s Failed to open bulk in pipe\r\n"),
            pszFname));
        goto EXIT;
    }

    // Prepare for command transfer
    ReceiveCBW();
    
    fResult = TRUE;
    
EXIT:
    FUNCTION_LEAVE_MSG();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -