📄 trans.cpp
字号:
{
BOOL bIsTransDone = IsTransferDone(dwCurFrameIndex,dwCurMicroFrameIndex);
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer::DoneTransfer (this=0x%x,id=0x%x,curFrameIndex=0x%x, bIsTransDone=%d \r\n")
,this, m_dwTransferID, dwCurFrameIndex,bIsTransDone));
ASSERT(bIsTransDone == TRUE);
if (bIsTransDone) {
DWORD dwUsbError = USB_NO_ERROR;
DWORD dwDataNotTransferred = 0;
DWORD dwFrameIndex =0 ;
DWORD dwOldPermissions = SetProcPermissions(m_dwCurrentPermissions);
// We have to update the buffer when this is IN Transfer.
if ((m_sTransfer.dwFlags & USB_IN_TRANSFER)!=NULL && m_pAllocatedForClient!=NULL) {
__try { // copying client buffer for OUT transfer
memcpy( m_sTransfer.lpvBuffer, m_pAllocatedForClient, m_sTransfer.dwBufferSize );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
// bad lpvBuffer.
if (dwUsbError == USB_NO_ERROR)
dwUsbError = USB_CLIENT_BUFFER_ERROR;
}
}
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
__try { // setting transfer status and executing callback function
if (m_sTransfer.lpfComplete !=NULL)
*m_sTransfer.lpfComplete = TRUE;
if (m_sTransfer.lpdwError!=NULL)
*m_sTransfer.lpdwError = dwUsbError;
if (m_sTransfer.lpdwBytesTransferred)
*m_sTransfer.lpdwBytesTransferred = m_DataTransferred;
if ( m_sTransfer.lpStartAddress ) {
( *m_sTransfer.lpStartAddress )(m_sTransfer.lpvNotifyParameter );
m_sTransfer.lpStartAddress = NULL ; // Make sure only do once.
}
} __except( EXCEPTION_EXECUTE_HANDLER ) {
}
#pragma prefast(pop)
SetProcPermissions(dwOldPermissions);
return (dwUsbError==USB_NO_ERROR);
}
else
return TRUE;
}
CSITransfer::CSITransfer (IN CIsochronousPipe * const pCPipe,IN CEhcd * const pCEhcd,STransfer sTransfer)
:CIsochTransfer(pCPipe, pCEhcd,sTransfer)
{
m_pCSITDList =0;
}
CSITransfer::~CSITransfer()
{
ASSERT(m_dwSchedTDIndex==m_dwNumOfTD);
ASSERT(m_dwDequeuedTDIndex == m_dwNumOfTD);
if (m_pCSITDList && m_dwNumOfTD) {
AbortTransfer();
for (DWORD dwIndex=0;dwIndex<m_dwNumOfTD;dwIndex++)
if (*(m_pCSITDList + dwIndex)) {
ASSERT((*(m_pCSITDList + dwIndex) )->GetLinkValid() != TRUE); // Invalid Next Link
GetPipe()->FreeCSITD(*(m_pCSITDList + dwIndex));
*(m_pCSITDList + dwIndex) = NULL;
}
delete m_pCSITDList;
}
}
BOOL CSITransfer::ArmTD()
{
BOOL bAnyArmed = FALSE;
if (m_pCSITDList && m_dwArmedTDIndex<m_dwNumOfTD ) { // Something TD wait for Arm.
DWORD dwCurDataPhysAddr = m_sTransfer.paBuffer + m_dwArmedBufferIndex ;
CSITD * pPrevCSITD= (m_dwArmedTDIndex==0?NULL:*(m_pCSITDList + m_dwArmedTDIndex-1));
while( m_dwArmedTDIndex < m_dwNumOfTD) {
DWORD dwLength= *(m_sTransfer.aLengths + m_dwArmedTDIndex);
*(m_pCSITDList + m_dwArmedTDIndex) = GetPipe()->AllocateCSITD( this,pPrevCSITD);
if (*(m_pCSITDList + m_dwArmedTDIndex) == NULL) {
break;
}
else {
pPrevCSITD = *(m_pCSITDList + m_dwArmedTDIndex);
BOOL bReturn=(*(m_pCSITDList + m_dwArmedTDIndex))->IssueTransfer(dwCurDataPhysAddr,dwCurDataPhysAddr+ dwLength -1, dwLength,
TRUE,// Interrupt On Completion
(m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0);
ASSERT(bReturn == TRUE);
// Interrupt on any CITD completion
(*(m_pCSITDList+ m_dwArmedTDIndex))->SetIOC(TRUE);
dwCurDataPhysAddr += dwLength;
m_dwArmedBufferIndex +=dwLength;
m_dwArmedTDIndex ++ ;
bAnyArmed = TRUE;
}
}
}
return bAnyArmed;
}
BOOL CSITransfer::AddTransfer()
{
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CSITransfer::AddTransfer (this=0x%x,id=0x%xm_dwFrameIndexStart=%x)\r\n"),this,m_dwTransferID,m_dwFrameIndexStart));
if (m_dwNumOfTD!=0 || m_pCSITDList != NULL) {
ASSERT(FALSE);
return FALSE;
}
m_dwNumOfTD = m_sTransfer.dwFrames ;
m_dwSchedTDIndex=0;
m_dwArmedTDIndex =0;
m_dwArmedBufferIndex=0;
m_dwFirstError = USB_NO_ERROR;
if (m_sTransfer.lpvBuffer && m_sTransfer.paBuffer && m_sTransfer.dwBufferSize) {
// Allocate space for CITD List
m_pCSITDList = (CSITD **)new PVOID[m_dwNumOfTD];
if (m_pCSITDList!=NULL) {
memset(m_pCSITDList,0,sizeof(CSITD *)*m_dwNumOfTD);
ArmTD();
return TRUE;
}
}
ASSERT(FALSE);
return FALSE;
}
BOOL CSITransfer::ScheduleTD(DWORD dwCurFrameIndex,DWORD /*dwCurMicroFrameIndex*/)
{
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CSITransfer::ScheduleTD (this=0x%x,id=0x%x,curFrameIndex=0x%x,m_dwFrameIndexStart=0x%x)\r\n"),this,m_dwTransferID, dwCurFrameIndex,m_dwFrameIndexStart));
BOOL bReturn = FALSE;
ArmTD();
if (m_dwSchedTDIndex < m_dwNumOfTD && m_pCSITDList !=0 && m_pCEhcd) {
if ((long)(dwCurFrameIndex - m_dwFrameIndexStart) > (long)m_dwSchedTDIndex) {
m_dwSchedTDIndex = dwCurFrameIndex - m_dwFrameIndexStart;
}
m_dwSchedTDIndex = min( m_dwSchedTDIndex , m_dwNumOfTD);
DWORD EndShedTDIndex = dwCurFrameIndex + (m_pCEhcd->GetPeriodicMgr()).GetFrameSize()-1;
DWORD dwNumTDCanSched;
if ( (long)(EndShedTDIndex - m_dwFrameIndexStart ) >= 0)
dwNumTDCanSched =EndShedTDIndex - m_dwFrameIndexStart ;
else // Too Early.
dwNumTDCanSched = 0;
dwNumTDCanSched= min(m_dwNumOfTD ,dwNumTDCanSched);
dwNumTDCanSched= min(m_dwArmedTDIndex ,dwNumTDCanSched);
if (m_dwSchedTDIndex < dwNumTDCanSched) { // Do scudule those index.
for (DWORD dwIndex = m_dwSchedTDIndex ; dwIndex<dwNumTDCanSched; dwIndex++) {
m_pCEhcd->PeriodQueueSITD(*(m_pCSITDList+dwIndex),m_dwFrameIndexStart + dwIndex );
(*(m_pCSITDList+dwIndex))->CheckStructure ();
ASSERT((*(m_pCSITDList+dwIndex))->m_pTrans == this);
}
m_dwSchedTDIndex = dwNumTDCanSched;
bReturn = TRUE;
}
}
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer::ScheduleTD (this=0x%x) return %d\r\n"),this,bReturn));
return bReturn;
}
BOOL CSITransfer::IsTransferDone(DWORD dwCurFrameIndex,DWORD /*dwCurMicroFrameIndex*/)
{
// Dequeue those TD has Transfered.
m_dwLastFrameIndex = dwCurFrameIndex - m_dwFrameIndexStart;
if ((long)(dwCurFrameIndex - m_dwFrameIndexStart)>= 1 ) {
DWORD dwTransfered = min(dwCurFrameIndex - m_dwFrameIndexStart , m_dwSchedTDIndex);
ASSERT(m_dwSchedTDIndex<=m_dwArmedTDIndex);
for (DWORD dwIndex=m_dwDequeuedTDIndex;dwIndex<dwTransfered && dwIndex < m_dwNumOfTD ; dwIndex++) {
if ( *(m_pCSITDList+dwIndex) != NULL && (*(m_pCSITDList + dwIndex) )->GetLinkValid()) {
(*(m_pCSITDList+dwIndex))->CheckStructure ();
ASSERT((*(m_pCSITDList+dwIndex))->m_pTrans == this);
m_pCEhcd->PeriodDeQueueTD((*(m_pCSITDList+dwIndex))->GetPhysAddr(),dwIndex + m_dwFrameIndexStart);
(*(m_pCSITDList + dwIndex) )->SetLinkValid(FALSE);
}
if (*(m_pCSITDList + dwIndex)!=NULL) {
DWORD dwTDError = USB_NO_ERROR;
(*(m_pCSITDList+dwIndex))->CheckStructure ();
if ((*(m_pCSITDList +dwIndex))->sITD_TransferState.sITD_TSContext.Active!=0)
dwTDError = USB_NOT_COMPLETE_ERROR;
else
if ((*(m_pCSITDList + dwIndex))->sITD_TransferState.sITD_TSContext.XactErr!=0)
dwTDError = USB_ISOCH_ERROR;
else
if ((*(m_pCSITDList + dwIndex))->sITD_TransferState.sITD_TSContext.BabbleDetected!=0)
dwTDError = USB_STALL_ERROR;
else
if ((*(m_pCSITDList + dwIndex))->sITD_TransferState.sITD_TSContext.DataBufferError!=0)
dwTDError = ((m_sTransfer.dwFlags & USB_IN_TRANSFER)!=0?USB_DATA_OVERRUN_ERROR:USB_DATA_UNDERRUN_ERROR);
else
if (((*(m_pCSITDList + dwIndex))->sITD_TransferState.dwSITD_TransferState & 0xff)!=0 )
dwTDError = USB_BIT_STUFFING_ERROR;
if (m_dwFirstError == USB_NO_ERROR ) { // only update first time
m_dwFirstError = dwTDError;
}
if (dwTDError!= USB_NO_ERROR) {
DEBUGMSG( ZONE_TRANSFER , (TEXT("CITransfer::DoneTransfer (this=0x%x, dwFrameIndex=%d) Error(%d) \r\n"),
this,dwIndex, dwTDError));
}
if (dwIndex< m_sTransfer.dwFrames) {
DWORD dwOldPermissions = SetProcPermissions(m_dwCurrentPermissions);
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
__try { // setting isoch OUT status parameters
m_sTransfer.adwIsochErrors[ dwIndex] = dwTDError;
m_sTransfer.adwIsochLengths[ dwIndex ] = *(m_sTransfer.aLengths + dwIndex) - (*(m_pCSITDList + dwIndex))->sITD_TransferState.sITD_TSContext.BytesToTransfer;
m_DataTransferred += m_sTransfer.adwIsochLengths[ dwIndex ];
} __except( EXCEPTION_EXECUTE_HANDLER ) {
}
#pragma prefast(pop)
SetProcPermissions(dwOldPermissions);
}
GetPipe()->FreeCSITD(*(m_pCSITDList + dwIndex));
*(m_pCSITDList + dwIndex) = NULL;
}
}
m_dwDequeuedTDIndex = dwIndex;
}
BOOL bReturn= ((long)(dwCurFrameIndex-m_dwFrameIndexStart)>=(long)m_dwNumOfTD);
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer:::IsTransferDone (this=0x%x,curFrameIndex=0x%x) return %d \r\n"),this, dwCurFrameIndex,bReturn));
return bReturn;
}
BOOL CSITransfer::AbortTransfer()
{
for (DWORD dwIndex=m_dwDequeuedTDIndex;dwIndex < m_dwNumOfTD && dwIndex<m_dwSchedTDIndex ; dwIndex++) {
if ( *(m_pCSITDList+dwIndex) != NULL ) {
BOOL bResult =m_pCEhcd->PeriodDeQueueTD((*(m_pCSITDList+dwIndex))->GetPhysAddr(),dwIndex + m_dwFrameIndexStart);
ASSERT(bResult == TRUE);
(*(m_pCSITDList + dwIndex) )->SetLinkValid(FALSE);
if (dwIndex< m_sTransfer.dwFrames) {
DWORD dwOldPermissions = SetProcPermissions(m_dwCurrentPermissions);
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
__try { // setting isoch OUT status parameters
m_sTransfer.adwIsochErrors[ dwIndex] = USB_NOT_COMPLETE_ERROR;
m_sTransfer.adwIsochLengths[ dwIndex ] = 0;
} __except( EXCEPTION_EXECUTE_HANDLER ) {
}
#pragma prefast(pop)
SetProcPermissions(dwOldPermissions);
}
if (m_dwFirstError == USB_NO_ERROR ) { // only update first time
m_dwFirstError = USB_NOT_COMPLETE_ERROR;
}
GetPipe()->FreeCSITD(*(m_pCSITDList + dwIndex));
*(m_pCSITDList + dwIndex) = NULL;
}
}
m_dwArmedTDIndex = m_dwDequeuedTDIndex = m_dwSchedTDIndex = m_dwNumOfTD;
Sleep(2); // Make Sure EHCI nolong reference to those TD;
return DoneTransfer(m_dwFrameIndexStart+m_dwNumOfTD, 0);
};
BOOL CSITransfer::DoneTransfer(DWORD dwCurFrameIndex,DWORD dwCurMicroFrameIndex)
{
BOOL bIsTransDone = IsTransferDone(dwCurFrameIndex, dwCurMicroFrameIndex);
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CITransfer::DoneTransfer (this=0x%x,id=0x%x,curFrameIndex=0x%x, bIsTransDone=%d \r\n")
,this,m_dwTransferID, dwCurFrameIndex,bIsTransDone));
ASSERT(bIsTransDone == TRUE);
if (bIsTransDone) {
DWORD dwOldPermissions = SetProcPermissions(m_dwCurrentPermissions);
// We have to update the buffer when this is IN Transfer.
if ((m_sTransfer.dwFlags & USB_IN_TRANSFER)!=NULL && m_pAllocatedForClient!=NULL) {
__try { // copying client buffer for OUT transfer
memcpy( m_sTransfer.lpvBuffer, m_pAllocatedForClient, m_sTransfer.dwBufferSize );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
// bad lpvBuffer.
if (m_dwFirstError == USB_NO_ERROR)
m_dwFirstError = USB_CLIENT_BUFFER_ERROR;
}
}
#pragma prefast(disable: 322, "Recover gracefully from hardware failure")
__try { // setting transfer status and executing callback function
if (m_sTransfer.lpfComplete !=NULL)
*m_sTransfer.lpfComplete = TRUE;
if (m_sTransfer.lpdwError!=NULL)
*m_sTransfer.lpdwError = m_dwFirstError;
if (m_sTransfer.lpdwBytesTransferred)
*m_sTransfer.lpdwBytesTransferred = m_DataTransferred;
if ( m_sTransfer.lpStartAddress ) {
( *m_sTransfer.lpStartAddress )(m_sTransfer.lpvNotifyParameter );
m_sTransfer.lpStartAddress = NULL ; // Make sure only do once.
}
} __except( EXCEPTION_EXECUTE_HANDLER ) {
}
#pragma prefast(pop)
SetProcPermissions(dwOldPermissions);
return (m_dwFirstError==USB_NO_ERROR);
}
else
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -