📄 bot.cpp
字号:
//
// 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 + -