📄 bot.c
字号:
DEBUGMSG( ZONE_ERR,(TEXT("BOT_DataTransfer error:%d\n"), dwErr));
SetLastError(dwErr);
return dwErr;
}
//
// We require exclusive entry into the transport.
// we could implement command queuing.
//
EnterCriticalSection(&pUsbDevice->Lock);
if ( !BOT_ResetAllPipes(pUsbDevice) ) {
DEBUGMSG( ZONE_ERR, (TEXT("BOT_ResetAllPipes failed!\n")));
dwErr = ERROR_GEN_FAILURE;
goto BOT_SendCommandDone;
}
ucStallCount = 0;
pUsbDevice->dwCurTag++;
memset( &Cbw, 0, dwCbwSize );
memset( &Csw, 0, dwCswSize );
//
// build the active CBW
//
Cbw.dCBWSignature = CBW_SIGNATURE;
Cbw.dCBWTag = pUsbDevice->dwCurTag;
Cbw.dCBWDataTransferLength = pData ? pData->RequestLength : 0;
if (Direction) {
Cbw.bmCBWFlags |= 0x80;
}
Cbw.bCBWLUN = (BYTE)(pCommand->dwLun & 0xf); // TBD
Cbw.bCBWCBLength = (UCHAR)pCommand->Length;
memcpy( &Cbw.CBWCB, pCommand->CommandBlock, pCommand->Length);
//
// 5.3.1 Command Block Transport
//
DEBUGMSG(ZONE_BOT,(TEXT("5.3.1 CBW\n")));
START_DT;
dwErr = IssueBulkTransfer( pUsbDevice->UsbFuncs,
pUsbDevice->BulkOut.hPipe,
DefaultTransferComplete, // Callback
pUsbDevice->BulkOut.hEvent, // Callback Context
USB_OUT_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK,// Flags
&Cbw, 0,
dwCbwSize,
&dwBytesTransferred,
pUsbDevice->Timeouts.CommandBlock,
&dwUsbErr );
STOP_DT( TEXT("CBW"), 10, pUsbDevice->Timeouts.CommandBlock);
if ( ERROR_SUCCESS != dwErr || USB_NO_ERROR != dwUsbErr || dwBytesTransferred != dwCbwSize ) {
DEBUGMSG( ZONE_ERR, (TEXT("BOT_DataTransfer error(5.3.1, %d, 0x%x, %d, %d, %d)\n"),
dwErr, dwUsbErr, dwBytesTransferred, dwCbwSize, pUsbDevice->Timeouts.CommandBlock));
bRc = BOT_ResetRecovery(pUsbDevice);
goto BOT_SendCommandDone;
}
//
// 5.3.2 Data Transport
//
if (pData && pData->DataBlock && pData->RequestLength)
{
PIPE pipeObj = Direction ? pUsbDevice->BulkIn : pUsbDevice->BulkOut;
DWORD dwFlags = Direction ? (USB_IN_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK) : (USB_OUT_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK);
BOOL fRet ;
DWORD dwTimeout = pCommand->Timeout;
DWORD dwStartTime=0;
DWORD dwUsbErr = USB_NOT_COMPLETE_ERROR;
DWORD dwTransferLength = 0 ;
ResetEvent(pipeObj.hEvent);
DEBUGMSG(ZONE_BOT,(TEXT("5.3.2 Data%sTransport - dwDataLength:%d, TimeOut:%d \n"), Direction ? TEXT("In") : TEXT("Out"), pData->RequestLength, dwTimeout ));
fRet = BulkTransferMgrTransfer(pipeObj.pAsyncContent, DefaultTransferComplete, pipeObj.hEvent,
dwFlags, pData->DataBlock, pData->RequestLength );
if (fRet ) {
if (!BulkTransferWait(pipeObj.pAsyncContent,dwTimeout)) {
fRet = BulkTransferMgrGetStatus(pipeObj.pAsyncContent, &dwTransferLength , &dwUsbErr);
dwUsbErr = USB_NOT_COMPLETE_ERROR;
}
else {
fRet = BulkTransferMgrGetStatus(pipeObj.pAsyncContent, &dwTransferLength , &dwUsbErr);
}
BulkTransferClose(pipeObj.pAsyncContent);
}
pData->TransferLength = dwTransferLength;
if ( USB_NO_ERROR != dwUsbErr ) {
UCHAR bIndex = Direction ? pUsbDevice->BulkIn.bIndex : pUsbDevice->BulkOut.bIndex;
// 6.7.x.3: the host shall clear the Bulk pipe
DEBUGMSG( ZONE_ERR, (TEXT("BOT_DataTransfer warning(6.7.x.3, RequestLength:%d TransferLength:%d Err:%d UsbErr:0x%x, dwTimeout:%d)\n"),
pData->RequestLength, dwTransferLength, dwErr, dwUsbErr, dwTimeout ));
// test/reset Bulk endpoint
dwResetErr = ResetBulkEndpoint( pUsbDevice->UsbFuncs,
pUsbDevice->hUsbDevice,
pipeObj.hPipe,
DefaultTransferComplete,
pipeObj.hEvent,
bIndex,
pUsbDevice->Timeouts.Reset );
if (ERROR_SUCCESS != dwResetErr) {
DEBUGMSG( ZONE_ERR, (TEXT("ResetBulkEndpoint.1 ERROR:%d\n"), dwResetErr));
bRc = BOT_ResetRecovery(pUsbDevice);
if (ERROR_SUCCESS == dwErr)
dwErr = ERROR_GEN_FAILURE;
goto BOT_SendCommandDone;
}
}
}
//
// 5.3.3 Command Status Transport (CSW)
//
ucStallCount = 0; // reset Stall count
DEBUGMSG(ZONE_BOT,(TEXT("5.3.3 CSW\n")));
_RetryCSW:
START_DT;
dwCswErr = IssueBulkTransfer( pUsbDevice->UsbFuncs,
pUsbDevice->BulkIn.hPipe,
DefaultTransferComplete, // Callback
pUsbDevice->BulkIn.hEvent, // Callback Context
(USB_IN_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK), // Flags
&Csw, 0,
dwCswSize,
&dwBytesTransferred,
pUsbDevice->Timeouts.CommandStatus,
&dwUsbErr );
STOP_DT( TEXT("CSW"), 100, (Direction ? pUsbDevice->Timeouts.CommandStatus : pCommand->Timeout) );
// Figure 2 - Status Transport Flow
if ( ERROR_SUCCESS != dwCswErr || USB_NO_ERROR != dwUsbErr ) {
DEBUGMSG( ZONE_ERR, (TEXT("BOT_DataTransfer error(5.3.3, dwCswErr:%d, dwUsbErr:0x%x, dwTimeout:%d)\n"),
dwCswErr, dwUsbErr, pUsbDevice->Timeouts.CommandStatus ));
START_DT;
// reset BulkIn endpoint
dwResetErr = ResetBulkEndpoint(pUsbDevice->UsbFuncs,
pUsbDevice->hUsbDevice,
pUsbDevice->BulkIn.hPipe,
DefaultTransferComplete,
pUsbDevice->BulkIn.hEvent,
pUsbDevice->BulkIn.bIndex,
pUsbDevice->Timeouts.Reset );
STOP_DT( TEXT("ResetBulkEndpoint.2"), 10, pUsbDevice->Timeouts.Reset );
if ( ERROR_SUCCESS == dwResetErr &&
++ucStallCount < MAX_BOT_STALL_COUNT ) {
DEBUGMSG( ZONE_WARN, (TEXT("Retry CSW\n")));
Sleep(ONE_FRAME_PERIOD);
goto _RetryCSW;
} else {
DEBUGMSG( ZONE_ERR, (TEXT("BOT_DataTransfer error(5.3.3, ResetErr:0x%x StallCount:%d)\n"), dwResetErr, ucStallCount));
bRc = BOT_ResetRecovery(pUsbDevice);
if (ERROR_SUCCESS == dwErr)
dwErr = ERROR_GEN_FAILURE;
goto BOT_SendCommandDone;
}
}
//
// Validate CSW...
//
// 6.3.1 Valid CSW: size
if ( dwBytesTransferred != dwCswSize ) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid Csw size: %d, %d\n"), dwBytesTransferred, dwCswSize ));
// 6.5 Host shall perform ResetRecovery for invalid CSW
bRc = BOT_ResetRecovery(pUsbDevice);
if (ERROR_SUCCESS == dwErr)
dwErr = ERROR_GEN_FAILURE;
goto BOT_SendCommandDone;
}
// 6.3.1 Valid CSW: Signature
if ( CSW_SIGNATURE != Csw.dCSWSignature) {
DEBUGMSG( ZONE_ERR, (TEXT("Invalid Csw.dCSWSignature:0x%x\n"), Csw.dCSWSignature ));
// 6.5 Host shall perform ResetRecovery for invalid CSW
bRc = BOT_ResetRecovery(pUsbDevice);
if (ERROR_SUCCESS == dwErr)
dwErr = ERROR_GEN_FAILURE;
goto BOT_SendCommandDone;
}
// 6.3.1 Valid CSW: Tags
if ( Cbw.dCBWTag != Csw.dCSWTag ) {
DEBUGMSG( ZONE_ERR, (TEXT("Mismatched Tags Cbw:0x%x Csw:0x%x\n"), Cbw.dCBWTag, Csw.dCSWTag ));
// 6.5 Host shall perform ResetRecovery for invalid CSW
bRc = BOT_ResetRecovery(pUsbDevice);
if (ERROR_SUCCESS == dwErr)
dwErr = ERROR_GEN_FAILURE;
goto BOT_SendCommandDone;
}
//
// Command Status?
//
if ( 0 == Csw.bCSWStatus || 1 == Csw.bCSWStatus ) {
if (1 == Csw.bCSWStatus ) {
DEBUGMSG( ZONE_WARN, (TEXT("Command Block Status: Command Failed\n")));
dwErr = ERROR_GEN_FAILURE;
}
goto BOT_SendCommandDone;
}
//
// Phase Error?
//
if ( 2 == Csw.bCSWStatus ) {
DEBUGMSG( ZONE_ERR, (TEXT("Command Block Status: Phase Error\n")));
// ignore the dCSWDataResidue
bRc = BOT_ResetRecovery(pUsbDevice);
if (ERROR_SUCCESS == dwErr)
dwErr = ERROR_GEN_FAILURE;
goto BOT_SendCommandDone;
}
BOT_SendCommandDone:
//
// cleanup
//
LeaveCriticalSection(&pUsbDevice->Lock);
DEBUGMSG(ZONE_TRACE,(TEXT("USBMSC<BOT_DataTransfer:%d\n"), dwErr));
return dwErr;
}
//
// Set a DWORD Value into an array of chars pointed to by pbArray
// (Little Endian)
//
VOID
SetDWORD(
IN OUT PUCHAR pbArray,
IN DWORD dwValue
)
{
if (pbArray) {
pbArray[3] = (UCHAR)dwValue;
dwValue >>= 8;
pbArray[2] = (UCHAR)dwValue;
dwValue >>= 8;
pbArray[1] = (UCHAR)dwValue;
dwValue >>= 8;
pbArray[0] = (UCHAR)dwValue;
}
return;
}
VOID
SetWORD(
PBYTE pBytes,
WORD wValue
)
{
if (pBytes) {
pBytes[1] = (BYTE)wValue;
wValue >>= 8;
pBytes[0] = (BYTE)wValue;
}
return;
}
//
// Gets a USHORT Value from an array of chars pointed to by pbArray.
// The return value is promoted to DWORD.
// (Little Endian)
//
DWORD
GetDWORD(
IN PUCHAR pbArray
)
{
DWORD dwReturn=0;
if (pbArray) {
dwReturn=*(pbArray++);
dwReturn=dwReturn*0x100 + *(pbArray++);
dwReturn=dwReturn*0x100 + *(pbArray++);
dwReturn=dwReturn*0x100 + *(pbArray++);
}
return dwReturn;
}
// EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -