?? bot.c
字號:
Cbw.dCBWTag = pUsbDevice->dwCurTag;
Cbw.dCBWDataTransferLength = pData ? pData->RequestLength : 0;
if (Direction) {
Cbw.bmCBWFlags |= 0x80;
}
Cbw.bCBWLUN = 0; // 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)
{
const USHORT wMaxPacketSize = Direction ? pUsbDevice->BulkIn.wMaxPacketSize : pUsbDevice->BulkOut.wMaxPacketSize;
// we don't provide our own phys buffer so are limited by USBD's max buffer size
const DWORD dwMaxBlock = (MAX_USB_BULK_LENGTH / wMaxPacketSize) * wMaxPacketSize;
PVOID pDataBlock = pData->DataBlock;
DWORD dwTransferLength = 0;
DWORD dwRequestLength = 0;
DWORD dwDataLength = pData->RequestLength;
DWORD dwTimeout = pCommand->Timeout;
DWORD dwStartTime=0;
DEBUGMSG(ZONE_BOT,(TEXT("5.3.2 Data%sTransport - dwDataLength:%d, TimeOut:%d \n"), Direction ? TEXT("In") : TEXT("Out"), dwDataLength, dwTimeout ));
while (dwDataLength && ((signed)dwTimeout > 0) )
{
dwRequestLength = min(dwMaxBlock, dwDataLength);
dwTransferLength = 0;
DEBUGMSG(ZONE_BOT,(TEXT("5.3.2 Data%sTransport - dwRequestLength:%d, TimeOut:%d \n"), Direction ? TEXT("In") : TEXT("Out"), dwRequestLength, dwTimeout ));
ASSERT( dwRequestLength <= MAX_USB_BULK_LENGTH );
dwStartTime = GetTickCount();
dwErr = IssueBulkTransfer( pUsbDevice->UsbFuncs,
Direction ? pUsbDevice->BulkIn.hPipe : pUsbDevice->BulkOut.hPipe,
DefaultTransferComplete,
Direction ? pUsbDevice->BulkIn.hEvent : pUsbDevice->BulkOut.hEvent,
Direction ? (USB_IN_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK) : (USB_OUT_TRANSFER|USB_NO_WAIT|USB_SHORT_TRANSFER_OK),
pDataBlock, 0,
dwRequestLength,
&dwTransferLength,
dwTimeout,
&dwUsbErr );
// 6.7.2.3: the host shall accept the data received
if ( (ERROR_SUCCESS == dwErr || ERROR_TIMEOUT == dwErr) &&
(USB_NO_ERROR == dwUsbErr || USB_STALL_ERROR == dwUsbErr) )
{
#if DEBUG
if ( dwTransferLength != dwRequestLength ) {
DEBUGMSG( ZONE_WARN, (TEXT("BOT_DataTransfer warning(6.7.2.3, RequestLength:%d TransferLength:%d Err:%d UsbErr:0x%x, dwTimeout:%d)\n"),
dwRequestLength, dwTransferLength, dwErr, dwUsbErr, dwTimeout ));
}
#endif
// adjust transfer length & buffer
ASSERT(dwTransferLength <= dwRequestLength);
pData->TransferLength += dwTransferLength;
dwDataLength -= dwTransferLength;
pDataBlock = (PVOID)((PBYTE)pDataBlock + 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"),
dwRequestLength, dwTransferLength, dwErr, dwUsbErr, dwTimeout ));
dwDataLength = 0;
START_DT;
// test/reset Bulk endpoint
dwResetErr = ResetBulkEndpoint( pUsbDevice->UsbFuncs,
pUsbDevice->hUsbDevice,
(Direction ? pUsbDevice->BulkIn.hPipe : pUsbDevice->BulkOut.hPipe),
DefaultTransferComplete,
(Direction ? pUsbDevice->BulkIn.hEvent : pUsbDevice->BulkOut.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;
}
STOP_DT( TEXT("ResetBulkEndpoint.1"), 10, pUsbDevice->Timeouts.Reset);
}
dwTimeout -= (GetTickCount() - dwStartTime);
}
}
//
// 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 (pData && pData->TransferLength) {
pData->TransferLength = Cbw.dCBWDataTransferLength - Csw.dCSWDataResidue;
//if (ERROR_SUCCESS != dwErr && ERROR_TIMEOUT != dwErr) {
// ASSERT(0);
//}
}
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 + -