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