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

📄 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 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name: 

        BOT.CPP

Abstract:

        USB Mass Storage Function Bulk-Only Transport.
        
--*/

//------------------------------------------------------------------------------
//
// Copyright (C) 2005-2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------ 

#include <windows.h>
#include <devload.h>
#include "usbfntypes.h"
#include "proxy.h"
#include "transporttypes.h"
#include "transport.h"

#if 0
#ifdef ZONE_INIT
#undef ZONE_INIT
#endif
#define ZONE_INIT 1

#ifdef ZONE_COMMENT
#undef ZONE_COMMENT
#endif
#define ZONE_COMMENT 1

#undef DEBUGMSG
#define DEBUGMSG(x,y) NKDbgPrintfW y
#undef RETAILMSG
#define RETAILMSG(x,y) NKDbgPrintfW y
#endif



#ifdef DEBUG

DBGPARAM dpCurSettings = {
    _T("usbmsfn"),
    {
        _T("Error"), _T("Warning"), _T("Init"), _T("Function"),
        _T("Comments"), _T(""), _T(""), _T(""),
        _T(""), _T(""), _T(""), _T(""), 
        _T(""), _T(""), _T(""), _T("")
    },
    0x5
};

#endif // DEBUG


// DLL entry point
extern "C"
BOOL
WINAPI
DllEntry(
    HINSTANCE hinstDll,
    DWORD     dwReason,
    LPVOID    lpReserved
    )
{
    SETFNAME(_T("DllEntry"));

    if (dwReason == DLL_PROCESS_ATTACH) {
        DEBUGREGISTER(hinstDll);
        DEBUGMSG(ZONE_INIT, (_T("%s Attached\r\n"), pszFname));
        DisableThreadLibraryCalls((HMODULE) hinstDll);
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        DEBUGMSG(ZONE_INIT, (_T("%s Detached\r\n"), pszFname));       
    }

    return TRUE;
}


#define dim(x) (sizeof(x)/sizeof((x)[0]))


#define BOT_RESET_REQUEST 0xFF
#define BOT_GET_MAX_LUN_REQUEST 0xFE


static TCHAR g_szActiveKey[MAX_PATH];


CRITICAL_SECTION g_cs;

HANDLE g_htTransfers;


enum CONTROL_RESPONSE {
    CR_SUCCESS = 0,
    CR_SUCCESS_SEND_CONTROL_HANDSHAKE, // Use if no data stage
    CR_STALL_DEFAULT_PIPE,
    CR_UNHANDLED_REQUEST,
};


typedef struct _PIPE_TRANSFER {
    PUFN_PIPE phPipe;
    HANDLE hev;
    UFN_TRANSFER hTransfer;
} PIPE_TRANSFER, *PPIPE_TRANSFER;

PIPE_TRANSFER g_rgPipeTransfers[] = 
    { { &g_hDefaultPipe }, { &g_hBIPipe }, { &g_hBOPipe } };


#define CONTROL_TRANSFER 0
#define IN_TRANSFER 1
#define OUT_TRANSFER 2


static LPCWSTR g_rgpszStrings0409[] = {
    g_RegInfo.szVendor, g_RegInfo.szProduct
#if 0
        , g_RegInfo.szSerialNumber
#endif
};

static UFN_STRING_SET g_rgStringSets[] = {
    0x0409, g_rgpszStrings0409, dim(g_rgpszStrings0409)
};


#ifdef DEBUG
    
static const LPCTSTR g_rgpszMscStates[] = {
    _T("unknown"),
    _T("idle"),
    _T("command transport"),
    _T("data in transport"),
    _T("data out transport"), 
    _T("status transport"),
    _T("wait for reset"), 
};

// Get a textual name of a device state.
static
LPCTSTR
GetMscStateName(
    MSC_STATE msc
    )
{
    DEBUGCHK(msc < dim(g_rgpszMscStates));
    LPCTSTR psz = g_rgpszMscStates[msc];
    return psz;
}
#endif

// Change the device state and print out a message.
static
inline
VOID
ChangeMscState(
    MSC_STATE msc
    )
{
    SETFNAME(_T("ChangeMscState"));
//    DEBUGMSG(ZONE_COMMENT, (_T("%s State change: %s -> %s\r\n"), pszFname,
//        GetMscStateName(g_MscState), GetMscStateName(msc)));
    g_MscState = msc;
}



// Read a configuration value from the registry.
static
BOOL
BOT_ReadConfigurationValue(
    HKEY    hClientDriverKey,
    LPCTSTR pszValue,
    PDWORD  pdwResult,
    BOOL    fMustSucceed
    )
{
    SETFNAME(_T("BOT_ReadConfigurationValue"));
    FUNCTION_ENTER_MSG();
    
    DWORD dwError = ERROR_SUCCESS;
    DWORD cbData = sizeof(DWORD);
    DWORD dwType;
    BOOL  fResult = TRUE;

    dwError = RegQueryValueEx(hClientDriverKey, pszValue, NULL, 
        &dwType, (PBYTE) pdwResult, &cbData);
    if ( (dwError != ERROR_SUCCESS) || (dwType != REG_DWORD) ) {
        if (fMustSucceed) {
            DEBUGMSG(ZONE_ERROR, (_T("%s Failed to read %s. Error %d\r\n"), 
                pszFname, pszValue, dwError));
        }
        fResult = FALSE;
    }
    else {
        DEBUGMSG(ZONE_INIT, (_T("%s %s = 0x%x\r\n"), 
            pszFname, pszValue, *pdwResult));
    }

    FUNCTION_LEAVE_MSG();

    return fResult;
}


// Configure the function controller based on registry settings.  This
// routine is not responsible for validating the data supplied by the registry.
static
BOOL
BOT_Configure(
    LPCTSTR pszActiveKey,
    HKEY hClientDriverKey
    )
{
    SETFNAME(_T("BOT_Configure"));
    FUNCTION_ENTER_MSG();
    
    DWORD dwRet = UfnGetRegistryInfo(pszActiveKey, &g_RegInfo);
    if (dwRet != ERROR_SUCCESS) {
        goto EXIT;
    }
    
    // Adjust device descriptors
    g_HighSpeedDeviceDesc.idVendor = (USHORT) g_RegInfo.idVendor;
    g_HighSpeedDeviceDesc.idProduct = (USHORT) g_RegInfo.idProduct;
    g_HighSpeedDeviceDesc.bcdDevice = (USHORT) g_RegInfo.bcdDevice;
    
    g_FullSpeedDeviceDesc.idVendor = g_HighSpeedDeviceDesc.idVendor;
    g_FullSpeedDeviceDesc.idProduct = g_HighSpeedDeviceDesc.idProduct;
    g_FullSpeedDeviceDesc.bcdDevice = g_HighSpeedDeviceDesc.bcdDevice;

#if 0
    DWORD cStrings = dim(g_rgpszStrings0409);
    DWORD iSerialNumber = 3;
    if (g_RegInfo.szSerialNumber[0] == 0) {
        DWORD dwSuccessSerialNumber = UfnGetSystemSerialNumber(
            g_RegInfo.szSerialNumber, dim(g_RegInfo.szSerialNumber));
        
        if (dwSuccessSerialNumber != ERROR_SUCCESS) {
            // No serial number
            cStrings = dim(g_rgpszStrings0409) - 1;
            iSerialNumber = 0;
        }
    }

    g_rgStringSets[0].cStrings = cStrings;
    g_HighSpeedDeviceDesc.iSerialNumber = (UCHAR) iSerialNumber;
    g_FullSpeedDeviceDesc.iSerialNumber = (UCHAR) iSerialNumber;
    
    UfnCheckPID(&g_HighSpeedDeviceDesc, &g_FullSpeedDeviceDesc, 
        PID_MICROSOFT_MASS_STORAGE_PROTOTYPE);
#endif

    if (!BOT_ReadConfigurationValue(hClientDriverKey, UMS_REG_BUFFER_VAL, 
            &g_cbDataBuffer, FALSE)) {
        g_cbDataBuffer = DEFAULT_DATA_BUFFER_SIZE;
    }

    dwRet = ERROR_SUCCESS;

EXIT:
    FUNCTION_LEAVE_MSG();
    
    return dwRet;
}


// Reset the transfer state of a pipe.
static
VOID
BOT_ResetPipeState(
    PUSB_PIPE_STATE pPipeState
    )
{
    SETFNAME(_T("BOT_ResetPipeState"));
    FUNCTION_ENTER_MSG();

    pPipeState->fSendingLess = FALSE;

    FUNCTION_LEAVE_MSG();
}


// Build a Command-Status packet.  The resulting packet is stored in
// g_rgbCXWBuffer.
static
VOID
BOT_BuildCSW(
    DWORD dwCSWTag,
    DWORD dwCSWDataResidue,
    BYTE  bCSWStatus
    )
{
    SETFNAME(_T("BOT_BuildCSW"));
    FUNCTION_ENTER_MSG();

    PCSW pCsw = (PCSW) g_rgbCXWBuffer;

    pCsw->dCSWSignature = CSW_SIGNATURE;
    pCsw->dCSWTag = dwCSWTag;
    pCsw->dCSWDataResidue = dwCSWDataResidue;
    pCsw->bCSWStatus = bCSWStatus;

    FUNCTION_LEAVE_MSG();
}

DWORD
static
WINAPI 
DefaultTransferComplete(
    PVOID pvNotifyParameter
    )
{   
    HANDLE hev = (HANDLE) pvNotifyParameter;

    DEBUGMSG(ZONE_COMMENT, (_T("BOT DefaultTransferComplete setting event\r\n")));

    SetEvent(hev);

    return ERROR_SUCCESS;
}


// Prepare to receive data from the host.
static
VOID
BOT_SetupRx(
    PPIPE_TRANSFER pPipeTransfer,
    PBYTE pbData,
    DWORD cbData
    )
{
    SETFNAME(_T("BOT_SetupRx"));
    FUNCTION_ENTER_MSG();

    DEBUGCHK(pbData != NULL);

    DWORD dwErr = g_pUfnFuncs->lpIssueTransfer(g_hDevice, *pPipeTransfer->phPipe, 
        &DefaultTransferComplete, pPipeTransfer->hev, USB_OUT_TRANSFER, cbData,
        pbData, 0, NULL, &pPipeTransfer->hTransfer);

    FUNCTION_LEAVE_MSG();
}


// Prepare to send data to the host.
static
VOID
BOT_SetupTx(
    PPIPE_TRANSFER pPipeTransfer,
    PBYTE pbData,
    DWORD cbData
    )
{
    SETFNAME(_T("BOT_SetupTx"));
    FUNCTION_ENTER_MSG();

    DEBUGCHK(pbData != NULL);

    DWORD dwErr = g_pUfnFuncs->lpIssueTransfer(g_hDevice, *pPipeTransfer->phPipe, 
        &DefaultTransferComplete, pPipeTransfer->hev, USB_IN_TRANSFER, 
        cbData, pbData, 0, NULL, &pPipeTransfer->hTransfer);

    FUNCTION_LEAVE_MSG();
}

// Return the configuration tree structure for the given speed.
static
PUFN_ENDPOINT
GetEndpointDescriptor(
    UFN_BUS_SPEED    Speed
    )
{
    DEBUGCHK( (Speed == BS_FULL_SPEED) || (Speed == BS_HIGH_SPEED) );
    PUFN_ENDPOINT pEndpoint;

    if (Speed == BS_HIGH_SPEED) {
        pEndpoint = &g_HighSpeedEndpoints[0];
    }
    else {
        pEndpoint = &g_FullSpeedEndpoints[0];
    }

    return pEndpoint;
}



// Get the pipe handle given an endpoint address.
static
UFN_PIPE
BOT_GetPipe(
    DWORD dwAddress
    )
{
    UFN_PIPE hPipe = NULL;
    
    PUFN_ENDPOINT pEndpoint= GetEndpointDescriptor(g_SpeedSupported);
        
    if (dwAddress == pEndpoint[0].Descriptor.bEndpointAddress) {
        hPipe = g_hBIPipe;
    }
    else if (dwAddress == pEndpoint[1].Descriptor.bEndpointAddress) {
        hPipe = g_hBOPipe;
    }
    
    return hPipe;
}




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

    if (g_MscState == MSC_STATE_IDLE) {
        g_dwCBWRead = 0;
        memset(g_rgbCXWBuffer, 0, sizeof(CBW));
        BOT_SetupRx(&g_rgPipeTransfers[OUT_TRANSFER], g_rgbCXWBuffer, sizeof(CBW));
        ChangeMscState(MSC_STATE_COMMAND_TRANSPORT);
    }

⌨️ 快捷键说明

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